JavaScript e Frontend Web

Integrando JS e HTML

/codes/w3c/hello-js/index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="js/index.js"></script>
</head>
<body>
  <h1 onclick="hello('Event')">Running Javascript</h1>
  <script>
    hello('Body Script');
  </script>
</body>
</html>
 
/codes/w3c/hello-js/index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="js/index.js"></script>
</head>
<body>
  <h1 onclick="hello('Event')">Running Javascript</h1>
  <script>
    hello('Body Script');
  </script>
</body>
</html>
 
/codes/w3c/hello-js/js/index.js
function hello(origin) {
  console.log(`Hello ${origin}!`);
}
 
hello('Head Script');
 
/codes/w3c/hello-js/js/index.js
function hello(origin) {
  console.log(`Hello ${origin}!`);
}
 
hello('Head Script');
 

Conteúdo Dinâmico

Open in GitHub

Arquivos
invest-app-read
├── data
│   └── investments.json
├── index.html
└── js
    ├── lib
    │   └── format.js
    └── main.js
Arquivos
invest-app-read
├── data
│   └── investments.json
├── index.html
└── js
    ├── lib
    │   └── format.js
    └── main.js
/codes/w3c/invest-app-read/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Invest App</title>
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD"
      crossorigin="anonymous"
    />
  </head>
  <body class="pb-5">
    <nav class="navbar navbar-expand-lg bg-body-tertiary">
      <div class="container">
        <a class="navbar-brand" href="#">Invest App</a>
        <button
          class="navbar-toggler"
          type="button"
          data-bs-toggle="collapse"
          data-bs-target="#navbarSupportedContent"
          aria-controls="navbarSupportedContent"
          aria-expanded="false"
          aria-label="Toggle navigation"
        >
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav me-auto mb-2 mb-lg-0">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">Home</a>
            </li>
          </ul>
        </div>
      </div>
    </nav>
 
    <div class="container">
      <h1 class="text-center my-5">Investimentos</h1>
      <div id="investment-grid" class="row row-cols-1 row-cols-md-3 g-4"></div>
    </div>
 
    <script
      src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN"
      crossorigin="anonymous"
    ></script>
    <script src="./js/main.js" type="module"></script>
  </body>
</html>
 
/codes/w3c/invest-app-read/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Invest App</title>
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD"
      crossorigin="anonymous"
    />
  </head>
  <body class="pb-5">
    <nav class="navbar navbar-expand-lg bg-body-tertiary">
      <div class="container">
        <a class="navbar-brand" href="#">Invest App</a>
        <button
          class="navbar-toggler"
          type="button"
          data-bs-toggle="collapse"
          data-bs-target="#navbarSupportedContent"
          aria-controls="navbarSupportedContent"
          aria-expanded="false"
          aria-label="Toggle navigation"
        >
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav me-auto mb-2 mb-lg-0">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">Home</a>
            </li>
          </ul>
        </div>
      </div>
    </nav>
 
    <div class="container">
      <h1 class="text-center my-5">Investimentos</h1>
      <div id="investment-grid" class="row row-cols-1 row-cols-md-3 g-4"></div>
    </div>
 
    <script
      src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN"
      crossorigin="anonymous"
    ></script>
    <script src="./js/main.js" type="module"></script>
  </body>
</html>
 
/codes/w3c/invest-app-read/data/investments.json
[
  {
    "id": 1,
    "name": "Tesouro Selic 2029",
    "value": 1000
  },
  {
    "name": "Tesouro Selic 2029",
    "value": 600,
    "id": 2
  }
]
 
/codes/w3c/invest-app-read/data/investments.json
[
  {
    "id": 1,
    "name": "Tesouro Selic 2029",
    "value": 1000
  },
  {
    "name": "Tesouro Selic 2029",
    "value": 600,
    "id": 2
  }
]
 
/codes/w3c/invest-app-read/js/main.js
import { formatCurrency } from './lib/format.js';
 
function InvestmentCard(investment) {
  return `<div class="col" id="investment-${investment.id}">
    <div class="card">
      <div class="card-header">
        <span class="investment-name">
          ${investment.name}
        </span>
      </div>
      <div class="card-body">
        <span>Valor:</span>
        <span class="investment-value">${formatCurrency(
          investment.value
        )}</span>
      </div>
    </div>
  </div>`;
}
 
function createInvestmentCard(investment) {
  const investmentContainer = document.querySelector(`#investment-grid`);
 
  investmentContainer.insertAdjacentHTML(
    'beforeend',
    InvestmentCard(investment)
  );
}
 
async function loadInvestmentCards() {
  const response = await fetch('data/investments.json');
 
  const investments = await response.json();
 
  for (const investment of investments) {
    createInvestmentCard(investment);
  }
}
 
loadInvestmentCards();
 
/codes/w3c/invest-app-read/js/main.js
import { formatCurrency } from './lib/format.js';
 
function InvestmentCard(investment) {
  return `<div class="col" id="investment-${investment.id}">
    <div class="card">
      <div class="card-header">
        <span class="investment-name">
          ${investment.name}
        </span>
      </div>
      <div class="card-body">
        <span>Valor:</span>
        <span class="investment-value">${formatCurrency(
          investment.value
        )}</span>
      </div>
    </div>
  </div>`;
}
 
function createInvestmentCard(investment) {
  const investmentContainer = document.querySelector(`#investment-grid`);
 
  investmentContainer.insertAdjacentHTML(
    'beforeend',
    InvestmentCard(investment)
  );
}
 
async function loadInvestmentCards() {
  const response = await fetch('data/investments.json');
 
  const investments = await response.json();
 
  for (const investment of investments) {
    createInvestmentCard(investment);
  }
}
 
loadInvestmentCards();
 

Formulário e Eventos

Back-end

REST API

MétodoCaminhoResposta
POST/investmentsCria um novo investmento
GET/investmentsRetorna todos os investments
GET/investments/1Retorna o investmento de ID 1
PUT/investments/1Atualiza o investmento de ID 1
DELETE/investments/1Exclui o investmento de ID 1
/codes/w3c/invest-app/back/db.json
{
  "investments": [
    {
      "name": "Tesouro Selic 2029",
      "value": 10000,
      "id": 1
    },
    {
      "name": "Tesouro IPCA 2029",
      "value": 10000,
      "id": 2
    }
  ]
}
/codes/w3c/invest-app/back/db.json
{
  "investments": [
    {
      "name": "Tesouro Selic 2029",
      "value": 10000,
      "id": 1
    },
    {
      "name": "Tesouro IPCA 2029",
      "value": 10000,
      "id": 2
    }
  ]
}

json-server:

$ npm init -y
$ npm install json-server
$ npm init -y
$ npm install json-server
/codes/w3c/invest-app/back/package.json
{
  "name": "foods-json-server",
  "version": "1.0.0",
  "description": "",
  "main": "src/index.js",
  "scripts": {
    "start": "json-server db.json",
    "server": "node src/index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "json-server": "^0.17.3"
  }
}
 
/codes/w3c/invest-app/back/package.json
{
  "name": "foods-json-server",
  "version": "1.0.0",
  "description": "",
  "main": "src/index.js",
  "scripts": {
    "start": "json-server db.json",
    "server": "node src/index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "json-server": "^0.17.3"
  }
}
 
$ npm start
$ npm start

GET http://localhost:3000/investments:

[
  {
    "name": "Server",
    "address": "10.0.0.10",
    "mask": "255.255.255.0",
    "id": 1
  },
  {
    "name": "PC 1",
    "address": "192.168.0.1",
    "mask": "255.255.255.0",
    "id": 2
  }
]
[
  {
    "name": "Server",
    "address": "10.0.0.10",
    "mask": "255.255.255.0",
    "id": 1
  },
  {
    "name": "PC 1",
    "address": "192.168.0.1",
    "mask": "255.255.255.0",
    "id": 2
  }
]

VS Code - Rest Client:

/codes/w3c/invest-app/back/requests.http
@host = http://localhost:3000
@createdInvestmentId = {{createdInvestment.response.body.$.id}}
 
### Create Investment
 
# @name createdInvestment
POST {{host}}/investments
Content-Type: application/json
 
{
  "name": "Tesouro Selic 2029",
  "value": 100
}
 
### Create Investment
 
# @name createdInvestment
POST {{host}}/investments
Content-Type: application/json
 
{
  "name": "Tesouro IPCA 2029",
  "value": 100
}
 
### Read Investments
 
GET {{host}}/investments
 
### Read Investments by Name
 
GET {{host}}/investments?name=Tesouro IPCA 2029
 
### Read Investment by Id
 
GET {{host}}/investments/{{createdInvestmentId}}
 
### Update Investment
 
PUT {{host}}/investments/{{createdInvestmentId}}
Content-Type: application/json
 
{
  "name": "Tesouro IPCA 2029",
  "value": 200
}
 
### Delete Investment
 
DELETE {{host}}/investments/{{createdInvestmentId}}
 
/codes/w3c/invest-app/back/requests.http
@host = http://localhost:3000
@createdInvestmentId = {{createdInvestment.response.body.$.id}}
 
### Create Investment
 
# @name createdInvestment
POST {{host}}/investments
Content-Type: application/json
 
{
  "name": "Tesouro Selic 2029",
  "value": 100
}
 
### Create Investment
 
# @name createdInvestment
POST {{host}}/investments
Content-Type: application/json
 
{
  "name": "Tesouro IPCA 2029",
  "value": 100
}
 
### Read Investments
 
GET {{host}}/investments
 
### Read Investments by Name
 
GET {{host}}/investments?name=Tesouro IPCA 2029
 
### Read Investment by Id
 
GET {{host}}/investments/{{createdInvestmentId}}
 
### Update Investment
 
PUT {{host}}/investments/{{createdInvestmentId}}
Content-Type: application/json
 
{
  "name": "Tesouro IPCA 2029",
  "value": 200
}
 
### Delete Investment
 
DELETE {{host}}/investments/{{createdInvestmentId}}
 

Create

request.http:

@host = http://localhost:3000
@createdInvestmentId = {{createdInvestment.response.body.$.id}}
 
### Create Investment
 
# @name createdInvestment
POST {{host}}/investments
Content-Type: application/json
 
{
  "name": "Tesouro IPCA 2029",
  "value": 100
}
@host = http://localhost:3000
@createdInvestmentId = {{createdInvestment.response.body.$.id}}
 
### Create Investment
 
# @name createdInvestment
POST {{host}}/investments
Content-Type: application/json
 
{
  "name": "Tesouro IPCA 2029",
  "value": 100
}

Read

request.http:

@host = http://localhost:3000
 
### Read Investments
 
GET {{host}}/investments
@host = http://localhost:3000
 
### Read Investments
 
GET {{host}}/investments

Update

request.http:

@host = http://localhost:3000
@createdInvestmentId = {{createdInvestment.response.body.$.id}}
 
### Update Investment
 
PUT {{host}}/investments/{{createdInvestmentId}}
Content-Type: application/json
 
{
  "name": "Tesouro IPCA 2029",
  "value": 200
}
@host = http://localhost:3000
@createdInvestmentId = {{createdInvestment.response.body.$.id}}
 
### Update Investment
 
PUT {{host}}/investments/{{createdInvestmentId}}
Content-Type: application/json
 
{
  "name": "Tesouro IPCA 2029",
  "value": 200
}

Delete

request.http:

@host = http://localhost:3000
@createdInvestmentId = {{createdInvestment.response.body.$.id}}
 
### Delete Investment
 
DELETE {{host}}/investments/{{createdInvestmentId}}
@host = http://localhost:3000
@createdInvestmentId = {{createdInvestment.response.body.$.id}}
 
### Delete Investment
 
DELETE {{host}}/investments/{{createdInvestmentId}}

Front-end

Open in GitHub

Arquivos
front
├── css
│   └── style.css
├── index.html
└── js
    ├── lib
    │   └── format.js
    ├── main.js
    └── services
        └── api.js
Arquivos
front
├── css
│   └── style.css
├── index.html
└── js
    ├── lib
    │   └── format.js
    ├── main.js
    └── services
        └── api.js
/codes/w3c/invest-app/front/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Invest App</title>
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD"
      crossorigin="anonymous"
    />
    <link rel="stylesheet" href="css/style.css" />
    <script src="https://code.iconify.design/3/3.1.0/iconify.min.js"></script>
  </head>
  <body class="pb-5">
    <nav class="navbar navbar-expand-lg bg-body-tertiary">
      <div class="container">
        <a class="navbar-brand" href="#">Invest App</a>
        <button
          class="navbar-toggler"
          type="button"
          data-bs-toggle="collapse"
          data-bs-target="#navbarSupportedContent"
          aria-controls="navbarSupportedContent"
          aria-expanded="false"
          aria-label="Toggle navigation"
        >
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav me-auto mb-2 mb-lg-0">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">Home</a>
            </li>
          </ul>
        </div>
      </div>
    </nav>
 
    <div class="container">
      <h1 class="text-center my-5">Investimentos</h1>
      <div id="investment-grid" class="row row-cols-1 row-cols-md-3 g-4"></div>
    </div>
 
    <div>
      <button
        class="btn btn-secondary create-investment"
        style="position: fixed; bottom: 24px; right: 24px"
        type="button"
        data-bs-toggle="offcanvas"
        data-bs-target="#offcanvasRight"
        aria-controls="offcanvasRight"
      >
        +
      </button>
    </div>
 
    <div
      class="offcanvas offcanvas-end"
      tabindex="-1"
      id="offcanvasRight"
      aria-labelledby="offcanvasRightLabel"
    >
      <div class="offcanvas-header">
        <h5 class="offcanvas-title" id="offcanvasRightLabel">
          Cadastro de Investimento
        </h5>
 
        <button
          type="button"
          id="offcanvas-close"
          class="btn-close"
          data-bs-dismiss="offcanvas"
          aria-label="Close"
        ></button>
      </div>
      <div class="offcanvas-body">
        <form>
          <div class="mb-3">
            <label for="name" class="form-label">Nome</label>
            <input
              type="name"
              class="form-control"
              id="name"
              name="name"
              placeholder="Ex: Tesouro Selic"
            />
          </div>
          <div class="mb-3">
            <label for="value" class="form-label">Valor</label>
            <input
              type="number"
              class="form-control"
              id="value"
              name="value"
              step="0.01"
              placeholder="100"
            />
          </div>
          <div class="mb-3">
            <input
              type="submit"
              class="form-control btn btn-secondary"
              id="submit"
              placeholder="100"
            />
          </div>
        </form>
      </div>
    </div>
 
    <div class="modal" tabindex="-1">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title">Remover Investimento</h5>
            <button
              type="button"
              class="btn-close"
              data-bs-dismiss="modal"
              aria-label="Close"
            ></button>
          </div>
          <div class="modal-body">
            <p>Deseja remover o investimento?</p>
          </div>
          <div class="modal-footer">
            <button
              type="button"
              class="btn btn-secondary"
              data-bs-dismiss="modal"
            >
              Fechar
            </button>
            <button type="button" class="btn btn-primary">Confirmar</button>
          </div>
        </div>
      </div>
    </div>
 
    <script
      src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN"
      crossorigin="anonymous"
    ></script>
    <script src="./js/main.js" type="module"></script>
  </body>
</html>
 
/codes/w3c/invest-app/front/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Invest App</title>
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD"
      crossorigin="anonymous"
    />
    <link rel="stylesheet" href="css/style.css" />
    <script src="https://code.iconify.design/3/3.1.0/iconify.min.js"></script>
  </head>
  <body class="pb-5">
    <nav class="navbar navbar-expand-lg bg-body-tertiary">
      <div class="container">
        <a class="navbar-brand" href="#">Invest App</a>
        <button
          class="navbar-toggler"
          type="button"
          data-bs-toggle="collapse"
          data-bs-target="#navbarSupportedContent"
          aria-controls="navbarSupportedContent"
          aria-expanded="false"
          aria-label="Toggle navigation"
        >
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav me-auto mb-2 mb-lg-0">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">Home</a>
            </li>
          </ul>
        </div>
      </div>
    </nav>
 
    <div class="container">
      <h1 class="text-center my-5">Investimentos</h1>
      <div id="investment-grid" class="row row-cols-1 row-cols-md-3 g-4"></div>
    </div>
 
    <div>
      <button
        class="btn btn-secondary create-investment"
        style="position: fixed; bottom: 24px; right: 24px"
        type="button"
        data-bs-toggle="offcanvas"
        data-bs-target="#offcanvasRight"
        aria-controls="offcanvasRight"
      >
        +
      </button>
    </div>
 
    <div
      class="offcanvas offcanvas-end"
      tabindex="-1"
      id="offcanvasRight"
      aria-labelledby="offcanvasRightLabel"
    >
      <div class="offcanvas-header">
        <h5 class="offcanvas-title" id="offcanvasRightLabel">
          Cadastro de Investimento
        </h5>
 
        <button
          type="button"
          id="offcanvas-close"
          class="btn-close"
          data-bs-dismiss="offcanvas"
          aria-label="Close"
        ></button>
      </div>
      <div class="offcanvas-body">
        <form>
          <div class="mb-3">
            <label for="name" class="form-label">Nome</label>
            <input
              type="name"
              class="form-control"
              id="name"
              name="name"
              placeholder="Ex: Tesouro Selic"
            />
          </div>
          <div class="mb-3">
            <label for="value" class="form-label">Valor</label>
            <input
              type="number"
              class="form-control"
              id="value"
              name="value"
              step="0.01"
              placeholder="100"
            />
          </div>
          <div class="mb-3">
            <input
              type="submit"
              class="form-control btn btn-secondary"
              id="submit"
              placeholder="100"
            />
          </div>
        </form>
      </div>
    </div>
 
    <div class="modal" tabindex="-1">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title">Remover Investimento</h5>
            <button
              type="button"
              class="btn-close"
              data-bs-dismiss="modal"
              aria-label="Close"
            ></button>
          </div>
          <div class="modal-body">
            <p>Deseja remover o investimento?</p>
          </div>
          <div class="modal-footer">
            <button
              type="button"
              class="btn btn-secondary"
              data-bs-dismiss="modal"
            >
              Fechar
            </button>
            <button type="button" class="btn btn-primary">Confirmar</button>
          </div>
        </div>
      </div>
    </div>
 
    <script
      src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN"
      crossorigin="anonymous"
    ></script>
    <script src="./js/main.js" type="module"></script>
  </body>
</html>
 
/codes/w3c/invest-app/front/css/style.css
.card-header .icon-trash:hover,
.card-header .icon-pencil:hover {
  cursor: pointer;
}
 
.card-header .icon-trash,
.card-header .icon-pencil {
  font-size: 1.2rem;
}
 
/codes/w3c/invest-app/front/css/style.css
.card-header .icon-trash:hover,
.card-header .icon-pencil:hover {
  cursor: pointer;
}
 
.card-header .icon-trash,
.card-header .icon-pencil {
  font-size: 1.2rem;
}
 
/codes/w3c/invest-app/front/js/main.js
import API from './services/api.js';
import { formatCurrency } from './lib/format.js';
 
let removedHostId;
 
const bsOffcanvas = new bootstrap.Offcanvas('.offcanvas');
 
const confirmModal = new bootstrap.Modal('.modal');
 
function InvestmentCard(investment) {
  return `<div class="col" id="investment-${investment.id}">
    <div class="card">
      <div class="card-header">
        <span class="investment-name">
          ${investment.name}
        </span>
        <span class="float-end">
          <span class="icon-trash" >
            <span
              class="iconify"
              data-icon="solar:trash-bin-minimalistic-broken"
            >
            </span>
          </span>
          <span class="icon-pencil">
            <span
              class="iconify"
              data-icon="tabler:pencil"
            >
            </span>
          </span>
        </span>
      </div>
      <div class="card-body">
        <div>
          <span class="fw-bold">Valor:</span>
          <span class="investment-value">
            ${formatCurrency(investment.value / 100)}
          </span>
        </div>
      </div>
    </div>
  </div>`;
}
 
function createInvestmentCard(investment) {
  const investmentContainer = document.querySelector(`#investment-grid`);
 
  investmentContainer.insertAdjacentHTML(
    'beforeend',
    InvestmentCard(investment)
  );
 
  loadHandleConfirmModal(investment.id);
 
  loadHandleUpdateInvestment(investment.id);
}
 
async function loadInvestmentCards() {
  const investments = await API.read('/investments');
 
  for (const investment of investments) {
    createInvestmentCard(investment);
  }
}
 
function updateInvestmentCard({ id, name, value }) {
  document.querySelector(`#investment-${id} .investment-name`).innerText = name;
 
  document.querySelector(`#investment-${id} .investment-value`).innerText =
    formatCurrency(value / 100);
}
 
function loadHandleFormSubmit(type, id) {
  const form = document.querySelector('form');
 
  form.onsubmit = async (event) => {
    event.preventDefault();
 
    const investment = Object.fromEntries(new FormData(form));
 
    investment.value = Number(investment.value) * 100;
 
    if (type === 'create') {
      const createdInvestment = await API.create('/investments', investment);
 
      createInvestmentCard(createdInvestment);
    } else if (type === 'update') {
      const updatedInvestment = await API.update(
        `/investments/${id}`,
        investment
      );
 
      updateInvestmentCard(updatedInvestment);
    }
 
    form.reset();
 
    document.querySelector('#offcanvas-close').click();
  };
}
 
function loadHandleCreateInvestment() {
  const button = document.querySelector('.btn.create-investment');
 
  button.onclick = () => {
    bsOffcanvas.show();
 
    loadHandleFormSubmit('create');
  };
}
 
function loadHandleUpdateInvestment(id) {
  const iconPencil = document.querySelector(`#investment-${id} .icon-pencil`);
 
  iconPencil.onclick = async () => {
    const investment = await API.read(`/investments/${id}`);
 
    const { name, value } = investment;
 
    document.querySelector('form #name').value = name;
 
    document.querySelector('form #value').value = value / 100;
 
    bsOffcanvas.show();
 
    loadHandleFormSubmit('update', id);
  };
}
 
function loadHandleConfirmModal(id) {
  const iconTrash = document.querySelector(`#investment-${id} .icon-trash`);
 
  iconTrash.onclick = () => {
    removedHostId = id;
 
    confirmModal.show();
  };
}
 
function loadHandleRemoveInvestment() {
  const confirmBtn = document.querySelector('.modal .btn-primary');
 
  confirmBtn.onclick = () => {
    API.remove(`/investments/${removedHostId}`);
 
    document.querySelector(`#investment-${removedHostId}`).remove();
 
    confirmModal.hide();
  };
}
 
loadInvestmentCards();
 
loadHandleCreateInvestment();
 
loadHandleRemoveInvestment();
 
/codes/w3c/invest-app/front/js/main.js
import API from './services/api.js';
import { formatCurrency } from './lib/format.js';
 
let removedHostId;
 
const bsOffcanvas = new bootstrap.Offcanvas('.offcanvas');
 
const confirmModal = new bootstrap.Modal('.modal');
 
function InvestmentCard(investment) {
  return `<div class="col" id="investment-${investment.id}">
    <div class="card">
      <div class="card-header">
        <span class="investment-name">
          ${investment.name}
        </span>
        <span class="float-end">
          <span class="icon-trash" >
            <span
              class="iconify"
              data-icon="solar:trash-bin-minimalistic-broken"
            >
            </span>
          </span>
          <span class="icon-pencil">
            <span
              class="iconify"
              data-icon="tabler:pencil"
            >
            </span>
          </span>
        </span>
      </div>
      <div class="card-body">
        <div>
          <span class="fw-bold">Valor:</span>
          <span class="investment-value">
            ${formatCurrency(investment.value / 100)}
          </span>
        </div>
      </div>
    </div>
  </div>`;
}
 
function createInvestmentCard(investment) {
  const investmentContainer = document.querySelector(`#investment-grid`);
 
  investmentContainer.insertAdjacentHTML(
    'beforeend',
    InvestmentCard(investment)
  );
 
  loadHandleConfirmModal(investment.id);
 
  loadHandleUpdateInvestment(investment.id);
}
 
async function loadInvestmentCards() {
  const investments = await API.read('/investments');
 
  for (const investment of investments) {
    createInvestmentCard(investment);
  }
}
 
function updateInvestmentCard({ id, name, value }) {
  document.querySelector(`#investment-${id} .investment-name`).innerText = name;
 
  document.querySelector(`#investment-${id} .investment-value`).innerText =
    formatCurrency(value / 100);
}
 
function loadHandleFormSubmit(type, id) {
  const form = document.querySelector('form');
 
  form.onsubmit = async (event) => {
    event.preventDefault();
 
    const investment = Object.fromEntries(new FormData(form));
 
    investment.value = Number(investment.value) * 100;
 
    if (type === 'create') {
      const createdInvestment = await API.create('/investments', investment);
 
      createInvestmentCard(createdInvestment);
    } else if (type === 'update') {
      const updatedInvestment = await API.update(
        `/investments/${id}`,
        investment
      );
 
      updateInvestmentCard(updatedInvestment);
    }
 
    form.reset();
 
    document.querySelector('#offcanvas-close').click();
  };
}
 
function loadHandleCreateInvestment() {
  const button = document.querySelector('.btn.create-investment');
 
  button.onclick = () => {
    bsOffcanvas.show();
 
    loadHandleFormSubmit('create');
  };
}
 
function loadHandleUpdateInvestment(id) {
  const iconPencil = document.querySelector(`#investment-${id} .icon-pencil`);
 
  iconPencil.onclick = async () => {
    const investment = await API.read(`/investments/${id}`);
 
    const { name, value } = investment;
 
    document.querySelector('form #name').value = name;
 
    document.querySelector('form #value').value = value / 100;
 
    bsOffcanvas.show();
 
    loadHandleFormSubmit('update', id);
  };
}
 
function loadHandleConfirmModal(id) {
  const iconTrash = document.querySelector(`#investment-${id} .icon-trash`);
 
  iconTrash.onclick = () => {
    removedHostId = id;
 
    confirmModal.show();
  };
}
 
function loadHandleRemoveInvestment() {
  const confirmBtn = document.querySelector('.modal .btn-primary');
 
  confirmBtn.onclick = () => {
    API.remove(`/investments/${removedHostId}`);
 
    document.querySelector(`#investment-${removedHostId}`).remove();
 
    confirmModal.hide();
  };
}
 
loadInvestmentCards();
 
loadHandleCreateInvestment();
 
loadHandleRemoveInvestment();
 
/codes/w3c/invest-app/front/js/lib/format.js
export function formatCurrency(value) {
  return Number(value).toLocaleString('pt-br', {
    style: 'currency',
    currency: 'BRL',
  });
}
 
/codes/w3c/invest-app/front/js/lib/format.js
export function formatCurrency(value) {
  return Number(value).toLocaleString('pt-br', {
    style: 'currency',
    currency: 'BRL',
  });
}
 

Fetch API

Funções da API: create, read, update e destroy

/codes/w3c/invest-app/front/js/services/api.js
const domain = 'http://localhost:3000';
 
async function create(resource, data) {
  const url = `${domain}${resource}`;
 
  const config = {
    method: 'POST',
    mode: 'cors',
    body: JSON.stringify(data),
    headers: {
      'Content-Type': 'application/json; charset=UTF-8',
    },
  };
 
  const res = await fetch(url, config);
 
  return await res.json();
}
 
async function read(resource) {
  const url = `${domain}${resource}`;
 
  const res = await fetch(url);
 
  return await res.json();
}
 
async function update(resource, data) {
  const url = `${domain}${resource}`;
 
  const config = {
    method: 'PUT',
    mode: 'cors',
    body: JSON.stringify(data),
    headers: {
      'Content-Type': 'application/json; charset=UTF-8',
    },
  };
 
  const res = await fetch(url, config);
 
  return await res.json();
}
 
async function remove(resource) {
  const url = `${domain}${resource}`;
 
  const config = {
    method: 'DELETE',
    mode: 'cors',
  };
 
  await fetch(url, config);
}
 
export default { create, read, update, remove };
 
/codes/w3c/invest-app/front/js/services/api.js
const domain = 'http://localhost:3000';
 
async function create(resource, data) {
  const url = `${domain}${resource}`;
 
  const config = {
    method: 'POST',
    mode: 'cors',
    body: JSON.stringify(data),
    headers: {
      'Content-Type': 'application/json; charset=UTF-8',
    },
  };
 
  const res = await fetch(url, config);
 
  return await res.json();
}
 
async function read(resource) {
  const url = `${domain}${resource}`;
 
  const res = await fetch(url);
 
  return await res.json();
}
 
async function update(resource, data) {
  const url = `${domain}${resource}`;
 
  const config = {
    method: 'PUT',
    mode: 'cors',
    body: JSON.stringify(data),
    headers: {
      'Content-Type': 'application/json; charset=UTF-8',
    },
  };
 
  const res = await fetch(url, config);
 
  return await res.json();
}
 
async function remove(resource) {
  const url = `${domain}${resource}`;
 
  const config = {
    method: 'DELETE',
    mode: 'cors',
  };
 
  await fetch(url, config);
}
 
export default { create, read, update, remove };
 

Create

API:

/codes/w3c/invest-app/front/js/services/api.js
async function create(resource, data) {
  const url = `${domain}${resource}`;
 
  const config = {
    method: 'POST',
    mode: 'cors',
    body: JSON.stringify(data),
    headers: {
      'Content-Type': 'application/json; charset=UTF-8',
    },
  };
 
  const res = await fetch(url, config);
 
  return await res.json();
}
/codes/w3c/invest-app/front/js/services/api.js
async function create(resource, data) {
  const url = `${domain}${resource}`;
 
  const config = {
    method: 'POST',
    mode: 'cors',
    body: JSON.stringify(data),
    headers: {
      'Content-Type': 'application/json; charset=UTF-8',
    },
  };
 
  const res = await fetch(url, config);
 
  return await res.json();
}
const investment = {
  name: "Tesouro IPCA 2029",
  value: 100
}
 
API.create('/investments', investment);
const investment = {
  name: "Tesouro IPCA 2029",
  value: 100
}
 
API.create('/investments', investment);

Read

API:

/codes/w3c/invest-app/front/js/services/api.js
async function read(resource) {
  const url = `${domain}${resource}`;
 
  const res = await fetch(url);
 
  return await res.json();
}
/codes/w3c/invest-app/front/js/services/api.js
async function read(resource) {
  const url = `${domain}${resource}`;
 
  const res = await fetch(url);
 
  return await res.json();
}
API.read('/investments');
API.read('/investments');

Update

API:

/codes/w3c/invest-app/front/js/services/api.js
async function update(resource, data) {
  const url = `${domain}${resource}`;
 
  const config = {
    method: 'PUT',
    mode: 'cors',
    body: JSON.stringify(data),
    headers: {
      'Content-Type': 'application/json; charset=UTF-8',
    },
  };
 
  const res = await fetch(url, config);
 
  return await res.json();
}
/codes/w3c/invest-app/front/js/services/api.js
async function update(resource, data) {
  const url = `${domain}${resource}`;
 
  const config = {
    method: 'PUT',
    mode: 'cors',
    body: JSON.stringify(data),
    headers: {
      'Content-Type': 'application/json; charset=UTF-8',
    },
  };
 
  const res = await fetch(url, config);
 
  return await res.json();
}
const investment = {
  name: "Tesouro IPCA 2029",
  value: 100
}
 
API.update('/investments/3', investment);
const investment = {
  name: "Tesouro IPCA 2029",
  value: 100
}
 
API.update('/investments/3', investment);

Delete

API:

/codes/w3c/invest-app/front/js/services/api.js
async function remove(resource) {
  const url = `${domain}${resource}`;
 
  const config = {
    method: 'DELETE',
    mode: 'cors',
  };
 
  await fetch(url, config);
}
/codes/w3c/invest-app/front/js/services/api.js
async function remove(resource) {
  const url = `${domain}${resource}`;
 
  const config = {
    method: 'DELETE',
    mode: 'cors',
  };
 
  await fetch(url, config);
}
API.remove('/investments/3');
API.remove('/investments/3');

Editar esta página