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
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étodo | Caminho | Resposta |
---|---|---|
POST | /investments | Cria um novo investmento |
GET | /investments | Retorna todos os investments |
GET | /investments/1 | Retorna o investmento de ID 1 |
PUT | /investments/1 | Atualiza o investmento de ID 1 |
DELETE | /investments/1 | Exclui 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
}
]
}
$ 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
}
]
/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
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');