npx create-react-app passwordgenerator
App.js
import React, { useState } from 'react'
import { toast, ToastContainer } from 'react-toastify'
import './App.css'
import {
numbers,
upperCaseLetters,
lowerCaseLetters,
specialCharacters,
} from './characters'
import 'react-toastify/dist/ReactToastify.css'
import { COPY_SUCCESS } from './message'
function App() {
const [password, setPassword] = useState('')
const [passwordLength, setPasswordLength] = useState(20)
const [includeUppercase, setIncludeUppercase] = useState(false)
const [includeLowercase, setIncludeLowercase] = useState(false)
const [includeNumbers, setIncludeNumbers] = useState(false)
const [includeSymbols, setIncludeSymbols] = useState(false)
const handleGeneratePassword = (e) => {
if (
!includeUppercase &&
!includeLowercase &&
!includeNumbers &&
!includeSymbols
) {
notify('You must Select atleast one option', true)
}
let characterList = ''
if (includeLowercase) {
characterList = characterList + lowerCaseLetters
}
if (includeUppercase) {
characterList = characterList + upperCaseLetters
}
if (includeNumbers) {
characterList = characterList + numbers
}
if (includeSymbols) {
characterList = characterList + specialCharacters
}
setPassword(createPassword(characterList))
}
const createPassword = (characterList) => {
let password = ''
const characterListLength = characterList.length
for (let i = 0; i < passwordLength; i++) {
const characterIndex = Math.round(Math.random() * characterListLength)
password = password + characterList.charAt(characterIndex)
}
return password
}
const copyToClipboard = () => {
const newTextArea = document.createElement('textarea')
newTextArea.innerText = password
document.body.appendChild(newTextArea)
newTextArea.select()
document.execCommand('copy')
newTextArea.remove()
}
const notify = (message, hasError = false) => {
if (hasError) {
toast.error(message, {
position: 'top-center',
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
})
} else {
toast(message, {
position: 'top-center',
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
})
}
}
const handleCopyPassword = (e) => {
if (password === '') {
notify('Nothing To Copy', true)
} else {
copyToClipboard()
notify(COPY_SUCCESS)
}
}
return (
<div className='App'>
<div className='container'>
<div className='generator'>
<h2 className='generator__header'>Password Generator</h2>
<div className='generator__password'>
<h3>{password}</h3>
<button onClick={handleCopyPassword} className='copy__btn'>
<i className='far fa-clipboard'></i>
</button>
</div>
<div className='form-group'>
<label htmlFor='password-strength'>Password length</label>
<input
defaultValue={passwordLength}
onChange={(e) => setPasswordLength(e.target.value)}
type='number'
id='password-strength'
name='password-strength'
max='100'
min='5'
/>
</div>
<div className='form-group'>
<label htmlFor='uppercase-letters'>Include Uppercase Letters</label>
<input
checked={includeUppercase}
onChange={(e) => setIncludeUppercase(e.target.checked)}
type='checkbox'
id='uppercase-letters'
name='uppercase-letters'
/>
</div>
<div className='form-group'>
<label htmlFor='lowercase-letters'>Include Lowercase Letters</label>
<input
checked={includeLowercase}
onChange={(e) => setIncludeLowercase(e.target.checked)}
type='checkbox'
id='lowercase-letters'
name='lowercase-letters'
/>
</div>
<div className='form-group'>
<label htmlFor='include-numbers'>Include Numbers</label>
<input
checked={includeNumbers}
onChange={(e) => setIncludeNumbers(e.target.checked)}
type='checkbox'
id='include-numbers'
name='include-numbers'
/>
</div>
<div className='form-group'>
<label htmlFor='include-symbols'>Include Symbols</label>
<input
checked={includeSymbols}
onChange={(e) => setIncludeSymbols(e.target.checked)}
type='checkbox'
id='include-symbols'
name='include-symbols'
/>
</div>
<button onClick={handleGeneratePassword} className='generator__btn'>
Generate Password
</button>
<ToastContainer
position='top-center'
autoClose={5000}
hideProgressBar={false}
newestOnTop={false}
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover
/>
</div>
</div>
</div>
)
}
export default App
App.css
.App {
min-height: 100vh;
background: #3b3b98;
}
.container {
width: 350px;
margin: 0 auto;
padding-top: 200px;
}
.generator {
background: #23235b;
border-radius: 3px;
box-shadow: 0px 2px 10px rgba(255, 255, 255, 0.2);
padding: 20px;
}
.generator__header {
text-align: center;
color: #fff;
margin-bottom: 20px;
}
.generator__password {
position: relative;
background: rgba(0, 0, 0, 0.4);
padding: 13px 10px;
color: #fff;
height: 46px;
margin-bottom: 15px;
}
.copy__btn {
position: absolute;
background: #3b3b98;
color: #fff;
border: none;
height: 40px;
padding: 10px;
cursor: pointer;
top: 3px;
right: 3px;
}
.generator__btn {
background: #3b3b98;
border: none;
display: block;
width: 100%;
padding: 10px;
color: #fff;
font-size: 17px;
cursor: pointer;
}
.form-group {
display: flex;
justify-content: space-between;
color: #fff;
margin-bottom: 15px;
}
characters.js
export const numbers = '0123456789'
export const upperCaseLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
export const lowerCaseLetters = 'abcdefghijklmnopqrstuvwxyz'
export const specialCharacters = "!'^+%&/()=?_#$½§{[]}|;:>÷`<.*-@é"
message.js
export const COPY_SUCCESS = 'Password successfully copied to clipboard'
Screenshot