diff --git a/public/index.html b/public/index.html index aa069f2..1634bcc 100644 --- a/public/index.html +++ b/public/index.html @@ -1,43 +1,17 @@ - + - + - - - React App + Password Generator - Fábio Augusto Mazuchi
- diff --git a/src/App.css b/src/App.css index 74b5e05..1d04334 100644 --- a/src/App.css +++ b/src/App.css @@ -1,38 +1,123 @@ -.App { - text-align: center; +* { + margin: 0; + padding: 0; + box-sizing: border-box; } -.App-logo { - height: 40vmin; - pointer-events: none; +main { + padding: 12px 3%; + margin: 20px auto; + width: 90%; + border-radius: 10px; + background-color: #0B112F; + display: flex; + flex-direction: column; } -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } +main h1 { + color: white; + margin-bottom: 20px; +} + +form { + display: flex; + flex-direction: column; +} + +form button { + background-color: #1D223F; + border: 0; + width: 100%; + border-radius: 8px; + padding: 20px 0; + color: white; + font-size: 18px; + cursor: pointer; + margin-bottom: 20px; + text-transform: uppercase; } -.App-header { - background-color: #282c34; - min-height: 100vh; +.container { + background-color: #1D223F; + padding: 18px 3%; display: flex; + margin-bottom: 12px; + border-radius: 8px; flex-direction: column; +} + +label { + display: flex; align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); + justify-content: space-between; color: white; } -.App-link { - color: #61dafb; +p { + margin: 4px; } -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); +.generate { + background-image: linear-gradient(to left, rgb(94, 107, 218), rgb(122, 135, 253)); + color: white; + text-align: center; + font-weight: bold; + margin-top: 10px; + font-size: 20px; +} + +.generate p { + word-break: break-all; +} + +.number p { + font-size: 14px; + color: #696B7F; + text-transform: uppercase; +} + +.number span { + color: white; +} + +.settings p { + font-size: 14px; + color: #696B7F; + text-transform: uppercase; +} + +input[type=range] { + width: 80%; + height: 3px; +} + +input[type=checkbox] { + display: none; +} + +.check { + width: 60px; + height: 35px; + border-radius: 20px; + background-color: #6E7081; + padding: 4px; + cursor: pointer; +} + +.check div { + height: 27px; + background-color: white; + width: 30px; + border-radius: 50%; +} + +.select { + background-color: #5E6BDA; + padding-left: 26px; +} + +@media screen and (min-width: 700px) { + main { + width: 60%; } } diff --git a/src/App.js b/src/App.js index 3784575..dead4fb 100644 --- a/src/App.js +++ b/src/App.js @@ -1,23 +1,13 @@ -import logo from './logo.svg'; import './App.css'; +import Form from './components/Form'; function App() { return (
-
- logo -

- Edit src/App.js and save to reload. -

- - Learn React - -
+
+

Password Generator

+
+
); } diff --git a/src/App.test.js b/src/App.test.js index 1f03afe..efd6d8a 100644 --- a/src/App.test.js +++ b/src/App.test.js @@ -1,8 +1,35 @@ import { render, screen } from '@testing-library/react'; import App from './App'; -test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); +beforeEach(() => { + render() +}); + +test('Verifica se existe o titulo "Password Generator"', () => { + const title = screen.getByRole('heading', { name: /password generator/i }) + const tamanho = "Password Generator".length; + expect(title.innerHTML.length).toBe(tamanho); + expect(title).toBeInTheDocument(); +}); + +test('Verifica se existe o botao com o texto "Click Generate"', () => { + const btn = screen.getByText(/click generate/i); + const tamanho = "Click Generate".length; + expect(btn.innerHTML.length).toBe(tamanho); + expect(btn).toBeInTheDocument(); +}); + +test('Verifica se ao carregar a página existe o texto "GENERATE PASSWORD"', () => { + const textGenerate = screen.getByText(/generate password/i); + const tamanho = "GENERATE PASSWORD".length; + expect(textGenerate.innerHTML.length).toBe(tamanho); + expect(textGenerate).toBeInTheDocument(); +}); + +test('Verifica se existe uma label com o texto "Include Uppercase"', () => { + const include = screen.getByLabelText(/include uppercase/i); + const tamanho = "Include Uppercase".length; + console.log(include.id); + expect(include.id.length).toBe(tamanho); + expect(include).toBeInTheDocument(); }); diff --git a/src/components/Checkbox.js b/src/components/Checkbox.js new file mode 100644 index 0000000..8e9ea1e --- /dev/null +++ b/src/components/Checkbox.js @@ -0,0 +1,31 @@ +import React, { Component } from "react"; + +class Checkbox extends Component { + render() { + const { textLabel, name, handleChange, checked } = this.props; + return ( +
+ +
+ ); + } +} + +export default Checkbox; diff --git a/src/components/Form.js b/src/components/Form.js new file mode 100644 index 0000000..3ed04c7 --- /dev/null +++ b/src/components/Form.js @@ -0,0 +1,95 @@ +import React, { Component } from "react"; +import Checkbox from "./Checkbox"; +import Number from "./Number"; +import { generatePass } from "../services/password"; + +class Form extends Component { + constructor() { + super(); + this.state = { + upperCase: false, + lowerCase: false, + numbers: false, + symbols: false, + symbols: false, + length: 32, + password: "GENERATE PASSWORD", + }; + this.handleChange = this.handleChange.bind(this); + this.getPass = this.getPass.bind(this); + this.addPass = this.addPass.bind(this); + } + + handleChange({ target }) { + const { name } = target; + const value = target.type !== "checkbox" ? target.value : target.checked; + this.setState( + { + [name]: value, + }, + () => this.getPass() + ); + } + + getPass() { + const { upperCase, symbols, numbers, length } = this.state; + return generatePass(upperCase, symbols, numbers, length); + } + + addPass() { + this.setState({ password: this.getPass() }); + localStorage.setItem("password", JSON.stringify(this.getPass())); + } + + render() { + const { length, password, upperCase, lowerCase, symbols, numbers } = + this.state; + return ( + +
+ +
+
+

+ Length: {length} +

+ +
+
+

settings

+ + + + +
+
+

{password}

+
+ + ); + } +} + +export default Form; diff --git a/src/components/Number.js b/src/components/Number.js new file mode 100644 index 0000000..65fe12d --- /dev/null +++ b/src/components/Number.js @@ -0,0 +1,25 @@ +import React, { Component } from "react"; + +class Number extends Component { + render() { + const { handleChange, name } = this.props; + return ( +
+ +
+ ); + } +} + +export default Number; diff --git a/src/services/password.js b/src/services/password.js new file mode 100644 index 0000000..481cc5f --- /dev/null +++ b/src/services/password.js @@ -0,0 +1,22 @@ +const letras = "abcdefghijklmnopqrstuvwxyz"; +const maiusculas = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +const caracter = "*&%$#-_:><~^"; +const numbers = "0123456789"; +const mai = false; +const car = false; +const num = false; +export const generatePass = (mai, car, num, len) => { + let senha = ""; + for (let i = 0; i < len; i++) { + if (mai) { + senha += maiusculas[Math.floor(Math.random() * maiusculas.length)]; + }if (car) { + senha += caracter[Math.floor(Math.random() * caracter.length)]; + } + if (num) { + senha += numbers[Math.floor(Math.random() * numbers.length)]; + } + senha += letras[Math.floor(Math.random() * letras.length)]; + } + return senha.substring(0, len); +};