From c0bae65c80c10009cc1ec5beac8e28faa1ef613d Mon Sep 17 00:00:00 2001 From: Josh S Date: Sat, 11 Mar 2023 18:34:00 -0500 Subject: [PATCH] First Commit --- README.md | 7 ++ package.json | 33 ++++++ public/index.html | 12 +++ public/robots.txt | 3 + src/App.jsx | 188 +++++++++++++++++++++++++++++++++++ src/Assets/CSS/App.min.css | 77 ++++++++++++++ src/Assets/CSS/Index.min.css | 5 + src/Components/Characters.js | 4 + src/Components/Message.js | 1 + src/index.js | 11 ++ 10 files changed, 341 insertions(+) create mode 100644 README.md create mode 100644 package.json create mode 100644 public/index.html create mode 100644 public/robots.txt create mode 100644 src/App.jsx create mode 100644 src/Assets/CSS/App.min.css create mode 100644 src/Assets/CSS/Index.min.css create mode 100644 src/Components/Characters.js create mode 100644 src/Components/Message.js create mode 100644 src/index.js diff --git a/README.md b/README.md new file mode 100644 index 0000000..fdcf04d --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# A simple password generator built in `React.js` + +`npm install` + +`npm start` + +# For build production run `npm run build` \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..16fd271 --- /dev/null +++ b/package.json @@ -0,0 +1,33 @@ +{ + "name": "password-gen", + "version": "0.1.0", + "private": true, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-scripts": "5.0.1", + "react-toastify": "^9.1.1" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..65cf646 --- /dev/null +++ b/public/index.html @@ -0,0 +1,12 @@ + + + + + + + Simple Password Generator + + +
+ + \ No newline at end of file diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..e9e57dc --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 0000000..68c4ed7 --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,188 @@ +import { React, useState} from 'react'; +import { toast, ToastContainer} from 'react-toastify'; +import './Assets/CSS/App.min.css'; +import { numbers, upperCaseLetters, lowerCaseLetters, specialCharacters } from './Components/Characters'; +import 'react-toastify/dist/ReactToastify.css'; +import { COPY_SUCCESS } from './Components/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('Error! 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: false, + progress: undefined, + }) + } else { + toast(message, { + position: 'top-center', + autoClose: 5000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: false, + progress: undefined, + }) + } + } + + const handleCopyPassword = (e) => { + if(password === '') { + notify('Error! Nothing to copy', true) + } else { + copyToClipboard() + notify(COPY_SUCCESS) + } + } + + return ( +
+
+
+

Simple Password Generator

+
+

{password}

+ +
+ +
+ + setPasswordLength(e.target.value)} + type='number' + id='password-strength' + name='password-strength' + max='22' + min='10' + /> +
+ +
+ + setIncludeUppercase(e.target.checked)} + type='checkbox' + id='uppercase-letters' + name='uppercase-letters' + /> +
+ +
+ + setIncludeLowercase(e.target.checked)} + type='checkbox' + id='lowercase-letters' + name='lowercase-letters' + /> +
+ +
+ + setIncludeNumbers(e.target.checked)} + type='checkbox' + id='include-numbers' + name='include-numbers' + /> +
+ +
+ + setIncludeSymbols(e.target.checked)} + type='checkbox' + id='include-symbols' + name='include-symbols' + /> +
+ + + +
+
+
+ ) +} + +export default App \ No newline at end of file diff --git a/src/Assets/CSS/App.min.css b/src/Assets/CSS/App.min.css new file mode 100644 index 0000000..fafab1e --- /dev/null +++ b/src/Assets/CSS/App.min.css @@ -0,0 +1,77 @@ +@import url(https://fonts.bunny.net/css?family=abril-fatface:400|rubik:600,800i,900i); + +.App { + min-height: 100vh; + background-color: #101725; +} + +.container { + width: 350px; + margin: 0 auto; + padding-top: 200px; +} + +.generator { + background-color: #0b0f19; + border-radius: 3px; + box-shadow: 0px 2px 10px rgba(255, 255, 255, 0.2); + padding: 20px; +} + +.generator__header { + text-align: center; + color: white; + margin-bottom: 20px; + font-family: 'Abril Fatface', display; + font-family: 'Rubik', sans-serif; +} + +.generator__password { + position: relative; + background-color: #101725; + padding: 13px 10px; + color: white; + height: 46px; + margin-bottom: 15px; + font-family: 'Abril Fatface', display; + font-family: 'Rubik', sans-serif; +} + +.copy__btn { + position: absolute; + background-color: #3b3b98; + color: white; + border: none; + height: 40px; + padding: 10; + cursor: pointer; + top: 3px; + right: 3x; +} + +.generator__btn { + background-color: #101725; + border: none; + display: block; + width: 100%; + padding: 10px; + color: white; + font-size: 17px; + cursor: pointer; + font-family: 'Abril Fatface', display; + font-family: 'Rubik', sans-serif; +} + +.form-group { + display: flex; + justify-content: space-between; + color: white; + margin-bottom: 15px; + font-family: 'Abril Fatface', display; + font-family: 'Rubik', sans-serif; +} + +.passgen-text { + font-family: 'Abril Fatface', display; + font-family: 'Rubik', sans-serif; +} \ No newline at end of file diff --git a/src/Assets/CSS/Index.min.css b/src/Assets/CSS/Index.min.css new file mode 100644 index 0000000..cc4077c --- /dev/null +++ b/src/Assets/CSS/Index.min.css @@ -0,0 +1,5 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} \ No newline at end of file diff --git a/src/Components/Characters.js b/src/Components/Characters.js new file mode 100644 index 0000000..63cf0c6 --- /dev/null +++ b/src/Components/Characters.js @@ -0,0 +1,4 @@ +export const numbers = '0123456789' +export const upperCaseLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +export const lowerCaseLetters = 'abcdefghijklmnopqrstuvwxyz' +export const specialCharacters = "!'^+%&/()=?_#$½§{[]}|;:>÷`<.*-@é" \ No newline at end of file diff --git a/src/Components/Message.js b/src/Components/Message.js new file mode 100644 index 0000000..37c2d36 --- /dev/null +++ b/src/Components/Message.js @@ -0,0 +1 @@ +export const COPY_SUCCESS = 'Password successfully copied to clipboard' \ No newline at end of file diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..ae9887d --- /dev/null +++ b/src/index.js @@ -0,0 +1,11 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import './Assets/CSS/Index.min.css'; +import App from './App'; + +ReactDOM.render( + + + , + document.getElementById('app') +) \ No newline at end of file