@@ -12,12 +12,80 @@ import refreshIcon from '../../assets/icons/refresh.svg'
1212import './index.css'
1313
1414const PasswordGenerator = ( ) => {
15- const [ passwordLength , setPasswordLength ] = useState < number > ( 10 )
15+ const [ passwordLength , setPasswordLength ] = useState < number > ( 8 )
16+ const [ password , setPassword ] = useState < string > ( '' )
17+ const [ copied , setCopied ] = useState < boolean > ( false )
18+ const [ includeUppercase , setIncludeUppercase ] = useState < boolean > ( true )
19+ const [ includeLowercase , setIncludeLowercase ] = useState < boolean > ( true )
20+ const [ includeNumbers , setIncludeNumbers ] = useState < boolean > ( true )
21+ const [ includeSpecialChars , setIncludeSpecialChars ] = useState < boolean > ( true )
22+
23+ const generatePassword = ( ) => {
24+ const uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
25+ const lowercase = 'abcdefghijklmnopqrstuvwxyz'
26+ const numbers = '0123456789'
27+ const specialChars = '!@#$%^&*()_+-=[]{}|;:,.<>?'
28+
29+ let allChars = ''
30+ if ( includeUppercase ) allChars += uppercase
31+ if ( includeLowercase ) allChars += lowercase
32+ if ( includeNumbers ) allChars += numbers
33+ if ( includeSpecialChars ) allChars += specialChars
34+
35+ if ( allChars === '' ) {
36+ setPassword ( '' )
37+ return
38+ }
39+
40+ let generatedPassword = ''
41+ for ( let i = 0 ; i < passwordLength ; i ++ ) {
42+ const randomIndex = Math . floor ( Math . random ( ) * allChars . length )
43+ generatedPassword += allChars [ randomIndex ]
44+ }
45+
46+ setPassword ( generatedPassword )
47+ }
48+
49+ useEffect ( ( ) => {
50+ if ( ! includeUppercase && ! includeLowercase && ! includeNumbers && ! includeSpecialChars ) {
51+ setIncludeLowercase ( true )
52+ return
53+ }
54+ generatePassword ( )
55+ } , [ passwordLength , includeUppercase , includeLowercase , includeNumbers , includeSpecialChars ] )
1656
1757 const onChangePasswordLength = ( value : any ) => {
1858 setPasswordLength ( value )
1959 }
2060
61+ const handleCopy = ( ) => {
62+ setCopied ( true )
63+ setTimeout ( ( ) => {
64+ setCopied ( false )
65+ } , 1000 )
66+ }
67+
68+ const getPasswordStrength = ( ) => {
69+ if ( passwordLength < 8 ) {
70+ return { text : 'Too short' , color : 'red' }
71+ }
72+
73+ const hasUppercase = / [ A - Z ] / . test ( password )
74+ const hasLowercase = / [ a - z ] / . test ( password )
75+ const hasNumber = / [ 0 - 9 ] / . test ( password )
76+ const hasSpecialChar = / [ ! @ # $ % ^ & * ( ) _ + \- = \[ \] { } | ; : , . < > ? ] / . test ( password )
77+
78+ const categoriesPresent = [ hasUppercase , hasLowercase , hasNumber , hasSpecialChar ] . filter ( Boolean ) . length
79+
80+ if ( categoriesPresent === 4 ) {
81+ return { text : 'Hard' , color : 'green' }
82+ } else if ( categoriesPresent === 3 ) {
83+ return { text : 'Medium' , color : 'orange' }
84+ } else {
85+ return { text : 'Weak' , color : 'red' }
86+ }
87+ }
88+
2189 return (
2290 < div className = "password-wrapper" >
2391 < div className = "gif" >
@@ -31,15 +99,19 @@ const PasswordGenerator = () => {
3199 </ div >
32100 < div className = "password-input-wrapper" >
33101 < div className = "password-field" >
34- < input type = "text" placeholder = "your password" value = "B9QI4PDBYY" />
35- < img src = { refreshIcon } alt = "refresh the password" />
102+ < input type = "text" placeholder = "your password" value = { password } readOnly />
103+ < img src = { refreshIcon } alt = "refresh the password" onClick = { generatePassword } style = { { cursor : 'pointer' } } />
36104 </ div >
37- < button className = "copy-btn" >
38- < img src = { copyIcon } alt = "copy password" />
39- Copy
40- </ button >
105+ < CopyToClipboard text = { password } onCopy = { handleCopy } >
106+ < button className = "copy-btn" >
107+ < img src = { copyIcon } alt = "copy password" />
108+ { copied ? 'Copied' : 'Copy' }
109+ </ button >
110+ </ CopyToClipboard >
41111 </ div >
42- < span className = "fw-500" > Weak</ span >
112+ < span className = "fw-500" style = { { color : getPasswordStrength ( ) . color } } >
113+ { getPasswordStrength ( ) . text }
114+ </ span >
43115 < div className = "slider" >
44116 < div >
45117 < label id = "slider-label" > Password Length: </ label >
@@ -54,14 +126,33 @@ const PasswordGenerator = () => {
54126 />
55127 </ div >
56128 < div className = "elements" >
57- < Checkbox id = "uppercase" label = "Uppercase" checked = { true } name = "upper" />
58- < Checkbox id = "lowercase" label = "Lowercase" checked = { false } name = "lower" />
59- < Checkbox id = "numbers" label = "Numbers" checked = { false } name = "numbers" />
129+ < Checkbox
130+ id = "uppercase"
131+ label = "Uppercase"
132+ checked = { includeUppercase }
133+ name = "upper"
134+ onChange = { ( e : any ) => setIncludeUppercase ( e . target . checked ) }
135+ />
136+ < Checkbox
137+ id = "lowercase"
138+ label = "Lowercase"
139+ checked = { includeLowercase }
140+ name = "lower"
141+ onChange = { ( e : any ) => setIncludeLowercase ( e . target . checked ) }
142+ />
143+ < Checkbox
144+ id = "numbers"
145+ label = "Numbers"
146+ checked = { includeNumbers }
147+ name = "numbers"
148+ onChange = { ( e : any ) => setIncludeNumbers ( e . target . checked ) }
149+ />
60150 < Checkbox
61151 id = "special chars"
62152 label = "Special Characters"
63- checked = { true }
153+ checked = { includeSpecialChars }
64154 name = "specialChars"
155+ onChange = { ( e : any ) => setIncludeSpecialChars ( e . target . checked ) }
65156 />
66157 </ div >
67158 </ div >
0 commit comments