11import { Button } from "flowbite-react" ;
22import { useTranslation } from "react-i18next" ;
3+ import { useState } from "react" ;
34
45const DownloadResumeButton = ( ) => {
5- const resumeLink = "/elazheri_iheb_resume.pdf" ;
66 const { t } = useTranslation ( ) ;
7+ const [ isOpen , setIsOpen ] = useState ( false ) ;
8+ const [ isDownloading , setIsDownloading ] = useState ( null ) ;
9+
10+ const languageOptions = [
11+ {
12+ code : 'fr' ,
13+ label : t ( 'downloadResume.french' ) ,
14+ flag : '🇫🇷' ,
15+ filename : '/iheb_elazheri_cv_fr.pdf'
16+ } ,
17+ {
18+ code : 'en' ,
19+ label : t ( 'downloadResume.english' ) ,
20+ flag : '🇺🇸' ,
21+ filename : '/iheb_elazheri_cv_en.pdf'
22+ }
23+ ] ;
24+
25+ const handleDownload = async ( option ) => {
26+ setIsDownloading ( option . code ) ;
27+
28+ // Create download link
29+ const link = document . createElement ( 'a' ) ;
30+ link . href = option . filename ;
31+ link . download = `Elazheri_Iheb_CV_${ option . code . toUpperCase ( ) } .pdf` ;
32+ document . body . appendChild ( link ) ;
33+ link . click ( ) ;
34+ document . body . removeChild ( link ) ;
35+
36+ // Reset states
37+ setTimeout ( ( ) => {
38+ setIsDownloading ( null ) ;
39+ setIsOpen ( false ) ;
40+ } , 1000 ) ;
41+ } ;
742
843 return (
9- < div className = "flex items-center justify-center mr-20" >
10- < a href = { resumeLink } download = "Elazheri Iheb CV.pdf" >
11- < Button
12- gradientDuoTone = "cyanToBlue"
13- className = "px-6 py-1 rounded-lg shadow-md transition-transform transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-cyan-600 text-color-black "
14- >
15- { t ( "navbar.cv" ) }
16- </ Button >
17- </ a >
44+ < div className = "relative flex items-center justify-center mr-20" >
45+ { /* Main Download Button */ }
46+ < Button
47+ onClick = { ( ) => setIsOpen ( ! isOpen ) }
48+ gradientDuoTone = "cyanToBlue"
49+ className = "px-6 py-1 rounded-lg shadow-md transition-all duration-300 transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-cyan-600 text-color-black relative"
50+ >
51+ < span className = "flex items-center gap-2" >
52+ 📄 { t ( "navbar.cv" ) }
53+ < svg
54+ className = { `w-4 h-4 transition-transform duration-300 ${ isOpen ? 'rotate-180' : '' } ` }
55+ fill = "none"
56+ stroke = "currentColor"
57+ viewBox = "0 0 24 24"
58+ >
59+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M19 9l-7 7-7-7" />
60+ </ svg >
61+ </ span >
62+ </ Button >
63+
64+ { /* Dropdown Menu */ }
65+ { isOpen && (
66+ < div className = "absolute top-full mt-2 bg-white dark:bg-gray-800 rounded-xl shadow-2xl border border-gray-200 dark:border-gray-700 min-w-[280px] z-50 animate-fadeIn" >
67+ { /* Header */ }
68+ < div className = "p-4 border-b border-gray-200 dark:border-gray-700" >
69+ < h3 className = "font-semibold text-gray-900 dark:text-white text-sm" >
70+ { t ( 'downloadResume.selectLanguage' ) }
71+ </ h3 >
72+ < p className = "text-xs text-gray-500 dark:text-gray-400 mt-1" >
73+ { t ( 'downloadResume.chooseVersion' ) }
74+ </ p >
75+ </ div >
76+
77+ { /* Language Options */ }
78+ < div className = "p-2" >
79+ { languageOptions . map ( ( option ) => (
80+ < button
81+ key = { option . code }
82+ onClick = { ( ) => handleDownload ( option ) }
83+ disabled = { isDownloading }
84+ className = "w-full flex items-center gap-3 p-3 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-all duration-200 group disabled:opacity-50 disabled:cursor-not-allowed"
85+ >
86+ < span className = "text-2xl" > { option . flag } </ span >
87+ < div className = "flex-1 text-left" >
88+ < div className = "font-medium text-gray-900 dark:text-white text-sm" >
89+ { option . label }
90+ </ div >
91+ < div className = "text-xs text-gray-500 dark:text-gray-400" >
92+ { t ( 'downloadResume.fileFormat' ) }
93+ </ div >
94+ </ div >
95+
96+ { /* Download Icon or Loading */ }
97+ < div className = "flex items-center" >
98+ { isDownloading === option . code ? (
99+ < div className = "flex items-center gap-2" >
100+ < div className = "animate-spin rounded-full h-4 w-4 border-b-2 border-cyan-600" > </ div >
101+ < span className = "text-xs text-cyan-600 font-medium" >
102+ { t ( 'downloadResume.downloading' ) }
103+ </ span >
104+ </ div >
105+ ) : (
106+ < svg
107+ className = "w-5 h-5 text-gray-400 group-hover:text-cyan-600 transition-colors"
108+ fill = "none"
109+ stroke = "currentColor"
110+ viewBox = "0 0 24 24"
111+ >
112+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
113+ </ svg >
114+ ) }
115+ </ div >
116+ </ button >
117+ ) ) }
118+ </ div >
119+ </ div >
120+ ) }
121+
122+ { /* Backdrop to close dropdown */ }
123+ { isOpen && (
124+ < div
125+ className = "fixed inset-0 z-40"
126+ onClick = { ( ) => setIsOpen ( false ) }
127+ />
128+ ) }
129+
130+ { /* Custom CSS for animations */ }
131+ < style jsx > { `
132+ @keyframes fadeIn {
133+ from {
134+ opacity: 0;
135+ transform: translateY(-10px);
136+ }
137+ to {
138+ opacity: 1;
139+ transform: translateY(0);
140+ }
141+ }
142+ .animate-fadeIn {
143+ animation: fadeIn 0.2s ease-out;
144+ }
145+ ` } </ style >
18146 </ div >
19147 ) ;
20148} ;
21149
22- export default DownloadResumeButton ;
150+ export default DownloadResumeButton ;
0 commit comments