1 / 11
Modulo 7 / APIs REST

Front-end Full-Stack

Consumindo a API de Produtos com HTML, CSS e JavaScript.

school Aula 33 schedule 2 horas

Visao geral

Arquitetura Full-Stack

Front-end
HTML + CSS + JS
fetch() API REST
Express.js
Banco
MongoDB

Front-end (esta aula)

  • HTML puro para estrutura
  • CSS puro para estilizacao (sem Tailwind)
  • JavaScript com fetch() para consumir a API
  • Servido pelo Express como arquivos estaticos

Back-end (aula 32)

  • Express.js com rotas REST
  • MongoDB + Mongoose
  • Autenticacao JWT
  • Error handler global

JavaScript

A Fetch API

download GET (buscar dados)

// Listar produtos const res = await fetch( '/api/produtos' ); const data = await res.json(); console.log(data.produtos);

upload POST (enviar dados)

const res = await fetch('/api/produtos', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ nome: 'Notebook', preco: 2999.90, categoria: 'Eletronicos' }) });

Implementacao

Listando produtos

code public/js/app.js

const API = '/api/produtos'; async function carregarProdutos() { const res = await fetch(API); const { produtos } = await res.json(); const lista = document.getElementById('lista-produtos'); lista.innerHTML = produtos.map(p => ` <div class="card-produto"> <h3>${p.nome}</h3> <p class="preco">R$ ${p.preco.toFixed(2)}</p> <span class="categoria">${p.categoria}</span> <button onclick="deletar('${p._id}')">Excluir</button> </div> `).join(''); } carregarProdutos();

Formulario

Criando produtos

code HTML do formulario

<form id="form-produto"> <input name="nome" placeholder="Nome do produto" required /> <input name="preco" type="number" step="0.01" placeholder="Preco" required /> <select name="categoria"> <option>Eletronicos</option> <option>Roupas</option> <option>Alimentos</option> <option>Livros</option> </select> <button type="submit">Adicionar</button> </form>

code JS do submit

const form = document .getElementById('form-produto'); form.addEventListener('submit', async (e) => { e.preventDefault(); const dados = Object.fromEntries( new FormData(form) ); dados.preco = Number(dados.preco); await fetch(API, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify(dados) }); form.reset(); carregarProdutos(); });

CRUD

Deletar e atualizar

delete Deletar

async function deletar(id) { if (!confirm('Excluir?')) return; await fetch(`${API}/${id}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${token}` } }); carregarProdutos(); }

edit Atualizar

async function atualizar(id, dados) { await fetch(`${API}/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify(dados) }); carregarProdutos(); }

Autenticacao

Login no front-end

let token = localStorage.getItem('token'); async function login(email, senha) { const res = await fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, senha }) }); if (!res.ok) return alert('Credenciais invalidas'); const data = await res.json(); token = data.token; localStorage.setItem('token', token); atualizarUI(); } function logout() { token = null; localStorage.removeItem('token'); atualizarUI(); } function atualizarUI() { document.getElementById('form-login').hidden = !!token; document.getElementById('painel-admin').hidden = !token; }

Servindo

express.static e CORS

folder Servindo o front

// No index.js do servidor app.use( express.static('public') ); // Estrutura da pasta public/ public/ index.html css/ style.css js/ app.js

info Quando servir junto ou separado?

  • Junto (express.static): ideal para projetos simples e MVPs
  • Separado: front em Vercel + API em outro host. Precisa de CORS.
  • Nesta aula: servimos junto para simplificar
// Se separar, habilitar CORS const cors = require('cors'); app.use(cors({ origin: 'https://meusite.com' }));

UX

Tratando erros no front

async function carregarProdutos() { const lista = document.getElementById('lista-produtos'); lista.innerHTML = '<p class="loading">Carregando...</p>'; try { const res = await fetch(API); if (!res.ok) throw new Error(`Erro ${res.status}`); const { produtos } = await res.json(); if (produtos.length === 0) { lista.innerHTML = '<p>Nenhum produto.</p>'; return; } // renderizar produtos... } catch (err) { lista.innerHTML = `<p class="erro">${err.message}</p>`; } }
Sempre mostre feedback visual: loading, estado vazio, e mensagens de erro.

Hora de praticar

Exercicio pratico

web Front-end para a API de Produtos

  1. Crie a pasta public/ no projeto da aula 32
  2. Crie index.html, css/style.css e js/app.js
  3. Implemente a listagem de produtos com fetch()
  4. Adicione o formulario de criacao com submit via POST
  5. Implemente login, armazenando o token no localStorage
  6. Adicione botao de excluir em cada produto
lightbulb Desafio: adicione filtro por categoria usando um select e edicao inline de preco.
Proxima aula

Aula 34

Documentação de APIs e testes com Postman.

task_alt O que aprendemos hoje

  • check_circleArquitetura full-stack (front + API + banco)
  • check_circleFetch API: GET, POST, PUT, DELETE
  • check_circleAutenticacao no front com localStorage
  • check_circleexpress.static para servir o front
  • check_circleTratamento de erros e feedback visual
Proxima aula
auto_stories Referencia: MDN Fetch API
Leandro Medeiros