# Trilha 1 - DevOps Linux, NodeJs, ReactJs ## Aula 06 ![EBT-logo](https://i.imgur.com/TWwpCwo.png) :::info 👨‍💻 **Prof** Edson Belem de Souza Junior 📞 **Celular/Whatsapp:** (21) 98199-0108 ✉ **E-mail:** profedsonbelem@gmail.com ::: :::info 👨‍💻 **Profª** Luciana de Vasconcelos Medeiros 📞 **Celular/Whatsapp:** (21) 98201-2525 ✉ **E-mail:** lu.vmedeiros@gmail.com ::: :::info 📕 **Aula:** 23/06/2024 🌐 **Site:** https://www.edsonbelemtreinamento.com.br/ **Blog**: https://edsonbelemtreinamento.com.br/#/blog **Youtube:** https://www.youtube.com/@EdsonBelemTreinamento **Instagram:** https://www.instagram.com/edson_belem_treinamento/ **Linkedin:** https://www.linkedin.com/in/edsonbelemsjunior/ ::: ## Tema da aula: Projeto ReactJs, LocalStorage, axios, Rotas, SweetAlert, Cors, Gravar, Logar ## Teoria: **LocalStorage:** O localStorage é uma funcionalidade de armazenamento local fornecida pelos navegadores web modernos. Ele permite que você armazene pares chave-valor diretamente no navegador do usuário, de forma que esses dados persistam mesmo após o fechamento do navegador. É uma maneira eficaz de manter informações no lado do cliente sem a necessidade de interações constantes com o servidor. **Características do localStorage** * Persistência: Os dados armazenados no localStorage persistem até serem explicitamente removidos, mesmo se o navegador for fechado e reaberto. * Capacidade de Armazenamento: Tipicamente, o localStorage oferece cerca de 5 a 10 MB de armazenamento por origem (domínio). * Escopo: Os dados armazenados são específicos ao domínio e ao protocolo (http/https). * Sincronização: Diferente do sessionStorage, o localStorage é compartilhado entre todas as abas e janelas que estão acessando a mesma origem. **Métodos do localStorage** Aqui estão os métodos básicos disponíveis no localStorage: * setItem(key, value): Armazena um item com a chave especificada. * getItem(key): Recupera o valor associado à chave especificada. * removeItem(key): Remove o item com a chave especificada. * clear(): Remove todos os itens armazenados. * key(index): Retorna a chave na posição especificada. **Limitações e Considerações** * Tamanho Limitado: O localStorage tem um limite de armazenamento que varia entre navegadores, geralmente entre 5 e 10 MB. * Segurança: Os dados armazenados no localStorage não são criptografados. Portanto, evite armazenar informações sensíveis como senhas. * Síncrono: Todas as operações do localStorage são síncronas, o que pode afetar o desempenho se usado para armazenar grandes volumes de dados. ### Dependencias: **axios:** Um cliente HTTP baseado em Promises para o navegador e node.js. Facilita a realização de requisições HTTP. Útil para: Fazer requisições para APIs, enviar e receber dados. **react-router-dom:** Biblioteca para gerenciar a navegação e roteamento no seu aplicativo React. Permite criar rotas dinâmicas e navegação entre diferentes páginas/visualizações. Útil para: Navegação e roteamento no aplicativo. **sweetalert2:** Biblioteca para criar alertas e diálogos bonitos e responsivos no navegador. Útil para: Mostrar alertas e diálogos no aplicativo. **cors:** Quando um navegador faz uma solicitação HTTP para um domínio diferente (origem) do domínio onde a página está hospedada, essa solicitação é considerada uma solicitação "cross-origin". Por razões de segurança, navegadores restringem essas solicitações cross-origin, impedindo que uma página web faça solicitações a um domínio diferente do seu. ## Projeto back-end NodeJs Instalar a dependencia do **cors** ``` npm i cors ``` Incluimos o **cors** para poder o front-end ter acesso ao banco de dados. **server.js** ```javascript= const express = require('express'); const bodyParser = require('body-parser'); const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const Users = require('./Model/Users'); const cors = require('cors'); const PORT = 3015; const chaveSecreta = 'minha palavra secreta DEUS'; require('./DataBase/Banco') const app = express(); app.use(bodyParser.json()); app.use(cors()); app.post('/api/users/save', async (req, res) => { try { let name = req.body.name; let password = req.body.password; let email = req.body.email; //validate ... (resgate ....) const hashPassword = await bcrypt.hash(password, 8); let users = new Users({ name, email, password: hashPassword, status: 'ACTIVATE', token: '' }); let respUser = await users.save(); res.status(200).send({ message: "Users Created" }); } catch (error) { res.status(500).send({ message: "Users Created Error" }) } }); app.post('/api/users/login', async (req, res) => { try { email = req.body.email; password = req.body.password; const users = await Users.findOne({ 'email': email }); if (!users) { throw new Error('Error no Login'); } const isLogin = await bcrypt.compare(password, users.password); if (!isLogin) { throw new Error('Error na Criptografia'); } const tokenGenerated = jwt.sign( { userId: users._id, email: users.email }, chaveSecreta, { expiresIn: '1h' } ) users.status = 'LOGIN' users.token = tokenGenerated; let respUser = await users.save(); // res.status(200).send({message:"Users Login","token":users.token}); res.status(200).send( { message: "Users Login", "token": users.token, 'users': respUser.name }); } catch (err) { res.status(500).send({ 'message': err.message }); } }); app.post('/api/users/logout', async (req, res) => { try { const myToken = req.body.token; const payload = jwt.verify(myToken, chaveSecreta); const users = await Users.findById(payload.userId); if (!users) { throw new Error('Error de autenticacao de Token'); } users.status = 'OFFLINE'; users.token = ''; await users.save(); res.status(200).send({ 'message': 'User Logout' }); } catch (err) { res.status(500).send({ 'message': err.message }); } }); app.listen(PORT, () => { console.log(`listener port: ${PORT}`) }); ``` ## Estrutura do Projeto ReactJs: ![image](https://hackmd.io/_uploads/rkrwXwxwA.png) . **Arquitetura do projeto:** ``` └───src │ App.css │ App.js │ App.test.js │ index.css │ index.js │ logo.svg │ readme.md │ reportWebVitals.js │ setupTests.js │ ├───config │ Routes.js │ ├───model │ Users.js │ ├───services │ AuthService.js │ └───views Cadastro.js Home.js Login.js ``` ## Classes e arquivos: readme.md ``` CRIAR O PROJETO npx create-react-app RODAR O PROJETO npm start PARAR O PROJETO CTRL + C - model - services - views - config DEPENDENCIA npm i axios sweetalert2 react-router-dom ``` **package.json** ```jsonld= { "name": "projetologin", "version": "0.1.0", "private": true, "dependencies": { "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "axios": "^1.7.2", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.0", "react-scripts": "5.0.1", "sweetalert2": "^11.12.1", "web-vitals": "^2.1.4" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, "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" ] } } ``` **Users.js** ```javascript= class Users { constructor(name, email, password, status) { this.name = name; this.email = email; this.password = password; this.status = status; } } export default Users; ``` **Routes.js** ```javascript= import { BrowserRouter as Router, Route, Routes } from "react-router-dom"; import Login from '../views/Login'; import Cadastro from '../views/Cadastro'; import Home from '../views/Home'; const AppRoutes = () => { return( <Router> <Routes> <Route path='/' element={<Cadastro />} /> <Route path='/login' element={<Login />} /> <Route path='/cadastro' element={<Cadastro />} /> <Route path='/home' element={<Home />} /> </Routes> </Router> ) } export default AppRoutes; ``` **App.js** ```javascript= import Routes from './config/Routes'; import './App.css'; function App() { return ( <div> <Routes /> </div> ); } export default App; ``` **AuthService.js** ```javascript= import axios from 'axios'; import Swal from 'sweetalert2'; const API = 'http://localhost:3015'; const save = async (name, email, password) => { try{ const resp = await axios.post(`${API}/api/users/save`, {name, email, password}); return resp.data; }catch(error){ throw error; } } const login = async (email, password) => { try { const resp = await axios.post(`${API}/api/users/login`, {email, password}); if(resp.data.token){ localStorage.setItem('user', JSON.stringify(resp.data)); } return resp.data; } catch (error) { throw error; } } const usuarioLogado= () => { return JSON.parse(localStorage.getItem('user')); } export default {save, login, usuarioLogado}; ``` **Login.js** ```javascript= import React, { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import AuthService from '../services/AuthService'; import Swal from 'sweetalert2'; const Login = () => { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const navigate = useNavigate(); const handleLogar = async (e) => { e. preventDefault(); try { const {token, users} = await AuthService.login(email, password); Swal.fire('Sucesso', 'Login realizado com sucesso', 'success'); localStorage.setItem('token', token); localStorage.setItem('users', users); navigate('/home'); } catch (error) { Swal.fire('Erro', 'Credenciais Invalidas', 'error'); } } return ( <div> <h2>Login</h2> <form onSubmit={handleLogar}> <div> <label>Email:</label> <input type='email' value={email} onChange={(e) => setEmail(e.target.value)} /> </div> <div> <label>Password:</label> <input type='password' value={password} onChange={(e) => setPassword(e.target.value)} /> </div> <button type='submit'>Logar</button> </form> <p>Não tem cadastro? <a href='/cadastro'>Vá para o Cadastro</a></p> </div> ); } export default Login; ``` **Cadastro.js** ```javascript= import React, {useState} from 'react'; import Swal from 'sweetalert2'; import AuthService from '../services/AuthService'; const Cadastro = () => { const [name, setName] = useState (''); const [email, setEmail] = useState (''); const [password, setPassword] = useState (''); const handleCadastrar = async (e) => { e.preventDefault(); try{ await AuthService.save(name, email, password); Swal.fire('Success', 'Cadastro de usuario com sucesso!', 'success'); }catch(error){ Swal.fire('Error', 'Erro no Cadastro...', 'error'); } } return( <div> <h2>Cadastro</h2> <form onSubmit={handleCadastrar}> <div> <label>Nome:</label> <input type='text' value={name} onChange={(e) => setName(e.target.value)} /> </div> <div> <label>Email:</label> <input type='email' value={email} onChange={(e) => setEmail(e.target.value)} /> </div> <div> <label>Password:</label> <input type='password' value={password} onChange={(e) => setPassword(e.target.value)} /> </div> <button type='submit'>Cadastrar</button> <p>Ja tem Cadastro? <a href='/login'>Faça o Login</a></p> </form> </div> ); } export default Cadastro; ``` **Home.js** ```javascript= import React, { useState, useEffect } from 'react'; const Home = () => { const [token, setToken] = useState(''); const [users, setUsers] = useState(''); useEffect(() => { const storedToken = localStorage.getItem('token'); setToken(storedToken); const storedUser = localStorage.getItem('users'); setUsers(storedUser); }) return ( <div> <h2>Bem-vindo, {users}</h2> <p>Token: {token}</p> </div> ); } export default Home; ``` ## Para rodar o projeto: No terminal, digitar: ``` npm start ``` *Aguardar abrir o browser* O projeto abrirá na página de **Cadastro**. http://localhost:3000/ ![image](https://hackmd.io/_uploads/r1i5PDxv0.png) . ![image](https://hackmd.io/_uploads/BkLwADxvR.png) Indo para a página de login ![image](https://hackmd.io/_uploads/HJ3JuPxv0.png) Digitando os dados para logar :::danger O projeto back-end tem que estar iniciado para funcionar o login ⭐ ::: ![image](https://hackmd.io/_uploads/BkZYOwxP0.png) . ![image](https://hackmd.io/_uploads/HJ_YCwlw0.png) Mostrando o localstorage ![image](https://hackmd.io/_uploads/Bkb2Awew0.png) :::info **EDSON BELEM TREINAMENTO** - edsonbelemtreinamento.com.br :::