# Trilha 1 - DevOps Linux, NodeJs, ReactJs
## Aula 06

:::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:

.
**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/

.

Indo para a página de login

Digitando os dados para logar
:::danger
O projeto back-end tem que estar iniciado para funcionar o login ⭐
:::

.

Mostrando o localstorage

:::info
**EDSON BELEM TREINAMENTO** - edsonbelemtreinamento.com.br
:::