OmniStack11: criando a interface web com ReacJS [Dia 03]

OmniStack11: criando a interface web com ReacJS [Dia 03]

Vamos lá começar o terceiro dia de semana Omnistack. Daremos prosseguimento ao projeto iniciado no primeiro dia na pasta frontend, criando a interface web com ReactJs.

Abaixo os links para todos os dias da Semana Omnistack 11

Limpando a estrutura do projeto ReactJS

Então abra o projeto com o VS Code e vamos montar a estrutura de pastas do projeto, mas primeiro vamos deletar os arquivos que não precisaremos.

Delete a lista abaixo que:

  • Na pasta src
    • app.css
    • App.test.js
    • index.css
    • logo.svg
    • serviceWorker.js
    • setupTests.js
  • Na pasta public
    • logo192.png
    • logo512.png
    • manifest.json
    • robots.txt

OK, na pasta src sobrou o App.js e o index.js . Agora você deve ajustar esse dois arquivos retirando as importações desnecessárias e alguns códigos não devem fazer parte projeto. Eles devem ficar assim

App.js

import React from 'react';

function App() {
  return (
   <h1>Hello World</h1>
  );
}

export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

Já na pasta public o arquivo deve ficar assim

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <title>Be The Hero</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>    
  </body>
</html>

Para visualizar se está tudo funcionando, acesse a pasta frontend pelo terminal e rode o comando yarn start. O servidor deve inicializar e o navegador abrir uma aba em localhost:3000 com o texto Hello World.

Estrutura de pastas da interface web com ReactJS

Se tudo funcionou vamos montar a nova estrutura. Para deixar o projeto mais fácil de atualizar crie todas as pasta e arquivos abaixo.

/frontend
  /src
    /assets
    /services
    /pages
      /Logon
       -index.js
       -styles.css
      /NewIncident
       -index.js
       -styles.css
      /Profile
       -index.js
       -styles.css
      /Register
       -index.js
       -styles.css

Na pasta assets por padrão ficam guardados os arquivos de imagens utilizados nas interfaces, baixe o logo.svg e o heroes.png clicando aqui e coloque na pasta.

Cada pasta dentro da pasta pages corresponde a uma tela. Por exemplo a página de login está dentro da pasta Logon, que contem os arquivos index.js e o styles.css

A pasta services conterá o arquivo do cliente HTTP que usaremos para consumir os dados do nosso backend.

Arquivo de rotas

Antes de iniciar o desenvolvimento da interface web com ReactJS vamos definir as rodas.

Crie o arquivo routes.js na pasta src. Importe todos os componentes (páginas), bem como o react-router-dom. Ele gerencia as rotas a partir dos componentes <BrowserRouter> e <Switch>.

O <BrowserRouter> deve estar por volta de todas rotas e o <Switch> vai garantir que apenas um rota seja acessada por vez.

import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';

import Logon from './pages/Logon';
import Register from './pages/Register';
import Profile from './pages/Profile';
import NewIncident from './pages/NewIncident';

export default function Routes() {
    return(
        <BrowserRouter>
            <Switch>
                <Route path="/" exact component={Logon} />
                <Route path="/register" component={ Register } />
                <Route path="/profile" component={ Profile } />
                <Route path="/incidents/new" component={ NewIncident } />
            </Switch>
        </BrowserRouter>
    );
}

O arquivo App.js também deve ser atualizado.

import React from 'react';

import Routes from './routes';

function App() {
  return (
    <Routes />
  );
}

export default App;

Falta somente mais um coisa para testar instalar o react-router-dom como dependência do projeto.

yarn add react-router-dom

Agora vamos começar o desenvolvimento da interface web com ReactJS.

Iniciando o layout da interface web com ReactJS

Um padrão utilizado no desenvolvimento de sistemas web é o reuso de código, pensando nessa perspectiva, é importante ter o máximo de componentes de interface em comum a todas a páginas definidas em um único arquivo.

Dessa forma é possível importar essas configurações em qualquer página do projeto, facilitando a manutenção do código.

Sendo assim crie na pasta src o arquivo global.css. Ele deve conter o fontes, modelos de input, botão e links comuns a todas as interfaces do projeto.

@import url('https://fonts.googleapis.com/css?family=Roboto:400,500,700&display=swap');

* {
    margin: 0;
    padding: 0;
    outline: 0;
    box-sizing: border-box;
}

body {
    font: 400 14px Roboto, sans-serif;
    background: #f0f0f5;
    -webkit-font-smoothing: antialiased;
}

input, button, textarea {
    font: 400 18px Roboto, sans-serif;
}

button {
    cursor: pointer;
}

form input {
    width: 100%;
    height: 60px;
    color: #333;
    border: 1px solid #dcdce6;
    border-radius: 8px;
    padding: 0 24px;
}

form textarea {
    width: 100%;
    resize: vertical;
    min-height: 140px;
    height: 60px;
    color: #333;
    border: 1px solid #dcdce6;
    border-radius: 8px;
    padding: 16px 24px;
    line-height: 24px;
}

.button {
    width: 100%;
    height: 60px;
    background: #e02041;
    border: 0;
    border-radius: 8px;
    color: #fff;
    font-weight: 700;
    margin-top: 16px;
    display: inline-block;
    text-align: center;
    text-decoration: none;
    font-size: 18px;
    line-height: 60px;
    transition: filter 0.2s;
}

.button:hove r {
    filter: brightness(90%);
}

.back-link {
    display: flex;
    align-items: center;
    margin-top: 40px;
    color: #41414d;
    font-size: 18px;
    text-decoration: none;
    font-weight: 500;
    transition: opacity 0.2s; 
}

.back-link {
    margin-right: 8px;
}

.back-link {
    opacity: 0.8;
}

Não esqueça de importar o global.css no App.css. Insira a linha abaixo no arquivo.

import './global.css';
Desenvolvendo a tela de login
OmniStack11: criando a interface web com ReacJS - tela de login

Essa imagem acima é a tela de login. Olhando por cima, temos um container, logo, um label no form, um input, um botão e um link para a página de cadastro.

import React from 'react';
import { FiLogIn } from 'react-icons/fi';
import { Link, useHistory } from 'react-router-dom';

import './styles.css';
import heroesImg from '../../assets/heroes.png';
import logo from '../../assets/logo.svg';

export default function Logon() {
  return (
    <div className="logonContainer">
    <section className="form">
        <img src={logo} alt="Be the hero"/>
        <form >
            <h1>Faça o seu logon</h1>
            <input placeholder="Sua ID" />
            <button className="button" type="submit">Entrar</button>
            <Link className="back-link" to="/register">
              <FiLogIn size={16} color="#E02041" />
                Não tenho cadastro
            </Link>
        </form>
    </section>
    <img src={heroesImg} alt="Heroes"/>
</div>
  );
}

Das dependências do login apenas o react-icons ainda não foi instalado no projeto. Use o comando abaixo para instalar

yarn add react-icons

Se você for testar ainda vai estar faltando a folha de estilos – styles.css

.logonContainer {
  width: 100%;
  max-width: 1120px;
  height: 100vh;
  margin: 0 auto;

  display: flex;
  align-items: center;
  justify-content: space-between;
}

.logonContainer section.form {
  width: 100%;
  max-width: 350px;
  margin-right: 30px;
}

.logonContainer section.form form {
  margin-top: 100px;
}

.logonContainer section.form form h1{
  font-size: 32px;
  margin-bottom: 32px;
}

Agora test com yarn start em localhost:3000 deve aparecer uma tela igual a do início da seção.

Bora que tá ficando bom. Vamos continuar criando a interface web com ReacJS.

Registro de ONGs

A página de registro de ONGs é bem parecida com a tela de login. O cadastro de ONGs tem o nome, email, whatsapp, cidade e estado da ONG.

import React, { useState } from 'react';
import { FiArrowLeft }  from 'react-icons/fi';
import { Link, useHistory } from 'react-router-dom';

import './styles.css';
import logoImg from '../../assets/logo.svg';

export default function Register() {
    return(
        <div className="register-container">
            <div className="content">
                <section>
                    <img src={logoImg} alt="Be Ther Hero" />
                    <h1>Cadastro</h1>
                    <p>Faça seu cadastro, entre na plataforma e ajude pessoas a encotrarem os casos da sua ONG</p>
                    <Link className="back-link" to="/">
                        <FiArrowLeft size={16} color="#E02041"/>
                        Já tenho cadastro
                    </Link>
                </section>
                <form>
                    <input placeholder="Nome da ONG" />                    
                    <input type="email" placeholder="E-mail" />                    
                    <input placeholder="Whatsapp" />
                    <div className="input-group">
                        <input placeholder="Cidade" />                        
                        <input placeholder="UF" style= {{ width: 80 }}/>
                    </div>
                    <button className="button" type="submit">Cadastrar</button>
                </form>
            </div>
        </div>
    );
}

O style.css deve ficar assim

.register-container {
  width: 100%;
  max-width: 1120px;
  height: 100vh;
  margin: 0 auto;

  display: flex;
  align-items: center;
  justify-content: center;
}

.register-container .content {
  width: 100%;
  padding: 96px;
  background: #f0f0f5;
  box-shadow: 0 0 100px rgba(0, 0,0, 0.1);
  border-radius: 8px;

  display: flex;
  justify-content: space-between;
  align-items: center;
}

.register-container .content section {
  width: 100%;
  max-width: 380px;
}

.register-container .content section h1 {
  margin: 64px 0 32px;
  font-size: 32px;
}

.register-container .content section p {
  font-size: 18px;
  color: #737380;
  line-height: 32px;
}

.register-container .content form {
  width: 100%;
  max-width: 450px;
}

.register-container .content form input {
  margin-top: 8px;
}

.register-container .content form .input-group {
  display: flex;
}

.register-container .content form .input-group input + input {
  margin-left: 8px;
}
Lista de Casos específicos de uma ONG

Essa lista é composta por cards, em 2 colunas, com os casos da ONG logada.

Criando interface web com reactjs

Código do componente Reactjs

import React, { useState , useEffect } from 'react';
import { Link, useHistory } from 'react-router-dom';
import { FiPower, FiTrash2 } from 'react-icons/fi';

import './styles.css';
import logoImg from '../../assets/logo.svg';

export default function Profile() {
    
    return(
        <div className="profile-container">
            <header>
                <img src={ logoImg } alt="Be the hero" />
                <span>Bem vindo, ONG Tal</span>

                <Link className="button" to="/incidents/new">Cadastrar novo caso</Link>
                <button type="button" onClick="">
                    <FiPower size={18} color="#E02041" />
                </button>
            </header>

            <h1>Casos cadastrados</h1>

                <ul>                    
                      <li>
                            <strong>CASO: </strong>
                            <p>título</p>    
                            <strong>DESCRICAO: </strong>
                            <p>descrição ...</p>    
                            <strong>Valor: </strong>
                            <p>R$ 199.00</p>    
                            <button onClick="" type="button">
                                <FiTrash2 size={20}  color="#a8a8b3"></FiTrash2>
                            </button>
                        </li>
                        <li>
                            <strong>CASO: </strong>
                            <p>título</p>    
                            <strong>DESCRICAO: </strong>
                            <p>descrição ...</p>    
                            <strong>Valor: </strong>
                            <p>R$ 199.00</p>    
                            <button onClick="" type="button">
                                <FiTrash2 size={20}  color="#a8a8b3"></FiTrash2>
                            </button>
                        </li>
                        <li>
                            <strong>CASO: </strong>
                            <p>título</p>    
                            <strong>DESCRICAO: </strong>
                            <p>descrição ...</p>    
                            <strong>Valor: </strong>
                            <p>R$ 199.00</p>    
                            <button onClick="" type="button">
                                <FiTrash2 size={20}  color="#a8a8b3"></FiTrash2>
                            </button>
                        </li>
                        <li>
                            <strong>CASO: </strong>
                            <p>título</p>    
                            <strong>DESCRICAO: </strong>
                            <p>descrição ...</p>    
                            <strong>Valor: </strong>
                            <p>R$ 199.00</p>    
                            <button onClick="" type="button">
                                <FiTrash2 size={20}  color="#a8a8b3"></FiTrash2>
                            </button>
                        </li>
                    
                </ul>

        </div>
    );
}

CSS

.profile-container {
  width: 100%;
  max-width: 1180px;
  padding: 0 30px;
  margin: 32px auto;
}

.profile-container  header {
  display: flex;
  align-items: center;
}

.profile-container  header span {
  font-size: 20px;
  margin-left: 24px;
}

.profile-container  header img {
  height: 64px;
}

.profile-container  header a {
  width: 260px;
  margin-left: auto;
  margin-top: 0;
}

.profile-container  header button {
  height: 60px;
  width: 60px;
  border-radius: 4px;
  border: 1px solid #dcdce6;
  background: transparent;
  margin-left: 16px;
  transition: border-color 0.2s;
}

.profile-container  header button:hover {
  border-color: #999;
}

.profile-container  h1 {
  margin-top: 80px;
  margin-bottom: 24px;
}

.profile-container  ul {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 24px;
  list-style: none;
}

.profile-container  ul li {
  background: #FFF;
  padding: 24px;
  border-radius: 8px;
  position: relative;
}

.profile-container  ul li button {
  position: absolute;
  right: 24px;
  top: 24px;
  border: 0;
}

.profile-container  ul li button:hover {
  opacity: 0.8;
}

.profile-container  ul li strong {
  display: block;
  margin-bottom: 16px;
  color: #41414d;
}

.profile-container  ul li p + strong {
  margin-top: 32px;   
}

.profile-container  ul li p {
  color: #737380;
  line-height: 21px;
  font-size: 16px;
}

Interface web de cadastro de caso.

criando interface web com reactjs

A ONG logada pode cadastrar seus casos para contato futuro pelos usuários app mobile, que será desenvolvido no próximo dia da Omnistack11.

Continue criando a interface web com o Reactjs

import React, { useState } from 'react';
import { Link, useHistory } from 'react-router-dom';
import logoImg from '../../assets/logo.svg';

import { FiArrowLeft } from 'react-icons/fi';
import './styles.css';

export default function NewIncident() {

 
    return(
        <div className="new-incident-container">
        <div className="content">
            <section>
                <img src={logoImg} alt="Be Ther Hero" />
                <h1>Cadastro novo caso</h1>
                <p>Descrever o caso detalhadamente para encontrar um herói para resolver isso.</p>
                <Link className="back-link" to="/profile">
                    <FiArrowLeft size={16} color="#E02041"/>
                    Voltar para home
                </Link>
            </section>
            <form onSubmit ="">
                <input 
                placeholder="Titulo do caso"
                value=""
                onChange=""/>               
                <textarea 
                placeholder="Descrição"
                value=""
                onChange="" 
                />
                <input
                 placeholder="Valor em reais"
                 value=""
                 onChange =""/>
                <button className="button" type="submit">Registrar</button>
            </form>
        </div>
    </div>
    );
}

CSS da tela registro de caso

.new-incident-container {
  width: 100%;
  max-width: 1120px;
  height: 100vh;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.new-incident-container .content {
  width: 100%;
  padding: 96px;
  background: #f0f0f5;
  box-shadow: 0 0 100px rgba(0, 0,0, 0.1);
  border-radius: 8px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.new-incident-container .content section {
  width: 100%;
  max-width: 380px;
}
.new-incident-container .content section h1 {
  margin: 64px 0 32pxnew-incident-container2px;
}
.new-incident-container .content section p {
  color: #737380;
  line-height: 32px;
}
.register-container .content form {
  width: 100%;
  max-width: 450px;
}
.new-incident-container .content form input,
.new-incident-container .content form textarea {
  margin-top: 8px;
}

Bem com esse último arquivo .css a esqueleto da aplicação ReactJS foi concluída.

No terminal digite yarn start e acesse localhost:3000/ para acessar o login.

Para acessar as outras rotas insira o recurso correspondente a tela que você deseja ver

Continuando o desenvolvimento do frontend com Reactjs

O precisamos fazer agora é configurar o Aaxios para consumir os dados do backend.

Instale o Axios pelo terminal pelo comando yarn add axios e crie dentro da pasta services o arquivo api.js.

Esse arquivo vai fazer a função de cliente HTTP. Insira o conteúdo abaixo no arquivo.

Lá você define de qual domínio que seu serviço vai consumir. No nosso caso é o localhost:3333. Já que o backend tá rodando na mesma máquina.

import axios from 'axios';

const api = axios.create({
    baseURL: 'http://localhost:3333',
})

export default api;
Consumir dados do backend

Primeiramente é preciso atualizar todos os componentes importando o axios com a linha import api from '../../services/api';.

Login com LocalStorage

O login vai precisar da importação do axios e do useHistory do react-router-dom. O usuário para autenticar deve inserir o código da ONG no input e clicar em ENTRAR.

Você tem que criar uma função acessar a rota/sessions do backend que vai dizer se aquele código é válido ou não. Se não for emite um alerta de código inválido. Se corresponder você salvar o id no localStorage pois as outras rotas precisarão para cadastrar ou listar o casos de um ONG.

Você também deve salvar o nome da ONG no localStorage. A lista de casos precisa dessa inforamção par mostrar o nome da ONG na tela.

import React, { useState } from 'react';
import './styles.css';
import { FiLogIn } from 'react-icons/fi';
import { Link, useHistory } from 'react-router-dom';

import api from '../../services/api';
import logo from '../../assets/logo.svg';
import heroesImg from '../../assets/heroes.png';

export default function Logon() {
    
    const [id, setId] = useState('');
    const history = useHistory();
    async function handleLogin(e) {
        e.preventDefault();
        try {
            console.log(id);
            const response = await api.post('sessions', { id });

            localStorage.setItem('ongId', id);
            localStorage.setItem('ongName',response.data.name);

            history.push('/profile');
        } catch {
            alert('Falha no login, tente novamente!');
        }
    }
    
    return(
        <div className="logonContainer">
            <section className="form">
                <img src={logo} alt="Be the hero"/>

                <form onSubmit={handleLogin}>
                    <h1>Faça o seu logon</h1>
                    <input
                     placeholder="Sua ID"
                     value={id}
                     onChange= {e => setId(e.target.value) }/>
                    <button className="button" type="submit">Entrar</button>

                    <Link className="back-link" to="/register">
                        <FiLogIn size={16} color="#E02041"/>
                        Não tenho cadastro
                    </Link>
                </form>
            </section>
            <img src={heroesImg} alt="Heroes"/>
        </div>
    );
}
Cadastrando de ONG

Com o useState você poder carregar os valores dos campos do formulário e depois usar o axios para passar para a API, que por fim salvará em banco de dados.

import React, { useState } from 'react';
import { FiArrowLeft }  from 'react-icons/fi';
import { Link, useHistory } from 'react-router-dom';
import api from '../../services/api';

import './styles.css';
import logoImg from '../../assets/logo.svg';

export default function Register() {
    const [name, setName] = useState('');
    const [email, setEmail] = useState('');
    const [whatsapp, setWhatsapp] = useState('');
    const [city, setCity] = useState('');
    const [uf, setUf] = useState('');

    const history = useHistory();
    async function handleRegister(e) {
        e.preventDefault();
        const data = {
            name,
            email,
            whatsapp,
            city,
            uf,
        };
        try {
            const response = await api.post('ongs', data);
            alert(`Seu ID de acesso: ${response.data.id}`);
            history.push('/');
        } catch {
            alert(`Erro no cadastro, tente novamente`);
        }
    }

    return(
        <div className="register-container">
            <div className="content">
                <section>
                    <img src={logoImg} alt="Be Ther Hero" />
                    <h1>Cadastro</h1>
                    <p>Faça seu cadastro, entre na plataforma e ajude pessoas a encotrarem os casos da sua ONG</p>


                    <Link className="back-link" to="/">
                        <FiArrowLeft size={16} color="#E02041"/>
                        Não tenho cadastro
                    </Link>
                </section>
                <form onSubmit={handleRegister}>
                    <input
                     placeholder="Nome da ONG"
                     value={name}
                     onChange={e => setName(e.target.value)}/>
                    
                    <input 
                    type="email" 
                    placeholder="E-mail"
                    value={email}
                     onChange={e => setEmail(e.target.value)}/>
                    
                    <input 
                    placeholder="Whatsapp"
                    value={whatsapp}
                     onChange={e => setWhatsapp(e.target.value)}/>

                    <div className="input-group">
                        <input 
                        placeholder="Cidade"
                        value={city}
                     onChange={e => setCity(e.target.value)}/>
                        
                        <input 
                        placeholder="UF"
                         style= {{ width: 80 }}
                         value={uf}
                        onChange={e => setUf(e.target.value)}/>
                    </div>

                    <button className="button" type="submit">Cadastrar</button>
                </form>
            </div>
        </div>
    );
}
Cadastro de um novo caso

O cadastro de um novo caso é bem parecido com o cadastro de ONGs a diferença é que o backend solicita o código da ONG logada que está salvo no localStorage, portanto você carregar essa informação e preencher o valor antes de fazer o insert com o axios.

import React, { useState } from 'react';
import { Link, useHistory } from 'react-router-dom';
import logoImg from '../../assets/logo.svg';

import { FiArrowLeft } from 'react-icons/fi';

import api from '../../services/api';

import './styles.css';

export default function NewIncident() {
    const [title, setTitle] = useState('');
    const [description,setDescription] = useState('');
    const [value, setValue] = useState('');

    const history = useHistory();
    const ongId = localStorage.getItem('ongId');

    async function handleSubmit(e) {
        e.preventDefault();
        const data = {
            title,
            description,
            value,
        }
        try {
            await api.post('incidents', data, {
                headers: {
                    Authorization: ongId,
                }
            })
            history.push('/profile');
        } catch {
            alert('Erro ao cadastrar caso, tente novamente');
        }
    }
 
    return(
        <div className="new-incident-container">
        <div className="content">
            <section>
                <img src={logoImg} alt="Be Ther Hero" />
                <h1>Cadastro novo caso</h1>
                <p>Descrever o caso detalhadamente para encontrar um herói para resolver isso.</p>
                <Link className="back-link" to="/profile">
                    <FiArrowLeft size={16} color="#E02041"/>
                    Voltar para home
                </Link>
            </section>
            <form onSubmit = {handleSubmit}>
                <input 
                placeholder="Titulo do caso"
                value= { title }
                onChange= {e => setTitle(e.target.value)}/>               
                <textarea 
                placeholder="Descrição"
                value={ description }
                onChange= {e => setDescription(e.target.value)}
                />
                <input
                 placeholder="Valor em reais"
                 value={value}
                 onChange = {e => setValue(e.target.value)}/>
                <button className="button" type="submit">Registrar</button>
            </form>
        </div>
    </div>
    );
}
Consumindo lista de casos do backend

A lista também precisa do ongId que está no localStorage para filtrar o os casos somente da ONG logada.

import React, { useState , useEffect } from 'react';
import { Link, useHistory } from 'react-router-dom';
import { FiPower, FiTrash2 } from 'react-icons/fi';

import api from '../../services/api';
import './styles.css';
import logoImg from '../../assets/logo.svg';

export default function Profile() {
    const [incidents, setIncidents] = useState([]);
    const history = useHistory();
    const ongId = localStorage.getItem('ongId');
    const ongName = localStorage.getItem('ongName');

    useEffect(() => {
        api.get('profile', {
            headers: {
                Authorization: ongId,
            }
        }).then(response => {
            setIncidents(response.data);
        })
    } ,[ongId]);

    async function handleDeleteIncident(id) {
        try {
            await api.delete(`incidents/${id}`, {
                headers: {
                    Authorization: ongId,
                }
            });
            setIncidents(incidents.filter(incident => incident.id !== id));
        } catch {
            alert('Erro ao deletar caso, tente novamente');
        }
    }

    function handleLogout() {
        localStorage.clear();
        history.push('/');
    }
    
    return(
        <div className="profile-container">
            <header>
                <img src={ logoImg } alt="Be the hero" />
                <span>Bem vindo, {ongName}</span>
                <Link className="button" to="/incidents/new">Cadastrar novo caso</Link>
                <button type="button" onClick={handleLogout}>
                    <FiPower size={18} color="#E02041" />
                </button>
            </header>
            <h1>Casos cadastrados</h1>
                <ul>
                    {incidents.map(incident => (
                            <li key={incident.id}>
                            <strong>CASO: </strong>
                            <p>{incident.title}</p>    
                            <strong>DESCRICAO: </strong>
                            <p>{incident.description}</p>    
                            <strong>Valor: </strong>
                            <p>{Intl.NumberFormat('pt-Br',{style: 'currency', currency: 'BRL'}).format(incident.value)}</p>    
                            <button onClick={() => handleDeleteIncident(incident.id)} type="button">
                                <FiTrash2 size={20}  color="#a8a8b3"></FiTrash2>
                            </button>
                        </li>
                    ))}
                </ul>
        </div>
    );
}

Conseguimos finalizar mais esse dia com sucesso!

O código integral está disponível no GitHub!

Tags: | | |

Sobre o Autor

Abner Oliveira
Abner Oliveira

Bombeiro Militar do CBMCE, Professor do CMCB. Mestre em Ciências da Computação pelo IFCE. Amante de desenvolvimento Web e Mobile. Iniciando no Marketing Digital.

1 Comentário

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *


Este site utiliza Cookies e Tecnologias semelhantes para melhorar a sua experiência. Ao utilizar nosso site você concorda que está de acordo com a nossa Política de Privacidade.