LB
Sistema WebCliente Real2026

EA Central

E-commerce de atacado com pedido pelo WhatsApp — vitrine React, painel administrativo e API Node/PostgreSQL

React 18TypeScriptVite 6React Router 7CSS custom propertiesNode.js 20
Roda emWebCelular (responsivo)PWA do painel
eacentral.com.br
produtos no catálogo
349
modelos de aparelho em 6 marcas
293
partes: vitrine, painel e API
3
dos preços recalculados no servidor
100%

01

Visão Geral

A EA Central Atacados é uma distribuidora de eletrônicos e acessórios no Brás (SP) que vendia por catálogo em PDF e lista no WhatsApp. O projeto nasceu como um protótipo HTML de página única e foi reconstruído por mim como aplicação full-stack em três partes: a vitrine React 18 + TypeScript (Vercel), a API Express + Prisma + PostgreSQL (Railway) e o painel administrativo, no mesmo front-end, onde o cliente cadastra produtos, categorias, marcas e modelos de aparelho, banners, pedidos e configurações. A regra de negócio do atacado vive no servidor: a tabela de preço por quantidade é do produto e não do modelo — 100 películas do A05 e 100 do iPhone 13 pagam a faixa de 200 —, e todo pedido é recalculado a partir do banco antes de virar mensagem de WhatsApp. O catálogo foi importado do PDF original com um pipeline próprio de extração e classificação, e o site já roda em produção com pedidos reais chegando pelo painel.

Meu papel

Desenvolvedor full-stack solo — modelagem do domínio, API REST com Prisma/PostgreSQL, front-end React/TypeScript da vitrine e do painel, importação do catálogo, integrações (WhatsApp, SuperFrete, Meta Pixel/CAPI, Pix), deploy Vercel + Railway e evolução contínua a partir dos pedidos do cliente.


Categoria

Sistema Web

Ano

2026

Status

Cliente Real

Plataformas

WebCelular (responsivo)PWA do painel

Vitrine e painel são o mesmo front-end React; a API é a única que fala com o banco e a única que decide preço. O WhatsApp é o canal de fechamento, não o sistema.

Vitrine + Painel

React 18 · Vercel

TypeScriptReact Router 7Vite

API REST

Express · Railway

PrismaZodJWTPino

Dados e mídia

PostgreSQL + volume

Postgres 16UploadsMigrations

Sincronização: POST /api/orders recalcula o pedido a partir do banco e devolve a URL do WhatsApp com a mensagem pronta.


02

O Problema

O lojista atendia pelo WhatsApp com catálogo em PDF: o cliente mandava lista por áudio, o consultor calculava preço de atacado na mão, errava faixa de desconto e perdia pedido na conversa. Não existia filtro por modelo de aparelho — o principal critério de quem compra capa e película — nem registro dos pedidos fora do celular do vendedor.

03 — A Solução

Uma vitrine rápida, feita para quem monta pedido grande: catálogo filtrado por categoria, marca e modelo de aparelho, ficha com preço por modelo e faixas de desconto, carrinho persistente com escolha de cores e versão, cotação de frete pelo CEP e um botão que registra o pedido na API e abre o WhatsApp com a mensagem pronta. Do outro lado, um painel onde o próprio cliente mantém o catálogo e acompanha os pedidos, com exportação para separação e conferência.


04

Por dentro do produto

O sistema em funcionamento, gravado da aplicação real com uma loja de demonstração — nenhuma tela é mockup.

01

Preço de atacado

A faixa de desconto cai sozinha quando o volume fecha

O cliente adiciona películas de vários modelos; o carrinho soma tudo por produto e avisa quanto falta para a próxima faixa. Ao passar de 200 unidades, o preço de cada linha cai — e o servidor recalcula o pedido inteiro antes de gerar a mensagem.

  • Tabela por produto, montada no painel só com a quantidade mínima de cada faixa
  • Escolha de cores com distribuição por unidade e versão masculina/feminina
  • Frete real por CEP (SuperFrete) ou retirada na loja
Preço de atacado
02

Compatibilidade

Filtro por aparelho e preço por modelo

Quem compra capa procura pelo celular, não pelo nome do produto. O catálogo filtra por marca e modelo, e a ficha mostra os modelos em chips na ordem de lançamento definida no painel — com o preço diferente quando um modelo custa mais.

  • 293 modelos em 6 marcas, cadastro global e vínculo por produto
  • Ordem natural (NOTE 7, NOTE 8, NOTE 8 PRO…) em vez de alfabética
  • Exceção de preço por modelo cadastrada só para quem foge do padrão
Compatibilidade
03

Painel

Um formulário que muda com a categoria

Capa pede modelo de aparelho e cores; cabo pede conector; caixa de som não pede nada disso. Três flags na categoria governam o que aparece, e um atalho revela a seção escondida quando o item foge da regra.

  • Faixas de preço com o fim de cada uma calculado a partir da seguinte
  • Aparelhos compatíveis com busca e marcação por marca
  • Upload validado pelo conteúdo, rotação corrigida e redução a 1600 px
Painel
04

Pedidos

Status, detalhe item a item e exportação para separar

Cada pedido guarda nome e preço no momento da compra. O painel mostra os itens com modelo, cores e ponta, muda o status em um clique e exporta o recorte do filtro em Excel ou PDF — lista para conferir o mês, ou um pedido por página para separar no estoque.

  • Exportação percorre até 2.000 pedidos, não só a página carregada
  • XLSX com valores como número e datas como data
  • PDF com cabeçalho repetido, zebra e continuação marcada
Pedidos
05

Celular

Feito para quem monta o pedido no telefone

Adicionar não abre a gaveta: sai um aviso com atalho e o contador pulsa. A gaveta, quando aberta pelo ícone, é uma folha de baixo com a página visível atrás. No painel, ↑ e ↓ substituem o arrastar para quem edita a ordem dos modelos com o dedo.

  • Carrinho persistente — um refresh não zera uma lista de 15 produtos
  • WhatsApp flutuante em todas as páginas
  • PWA do painel com página offline
Celular

05

6 fluxos em vídeo

Cada vídeo mostra uma tarefa completa, de ponta a ponta. Clique para assistir com controles.


06

Funcionalidades Principais

01

Preço progressivo por quantidade

Cada produto tem sua tabela (1–99 · 100+ · 300+). A faixa é conquistada pela soma de todos os modelos do mesmo produto no carrinho, que mostra quanto falta para o próximo degrau. O servidor valida a tabela e recalcula tudo no pedido.

02

Compatibilidade marca → modelo

Cadastro global de 6 marcas e 293 modelos, vinculados produto a produto. O catálogo filtra por aparelho, a ficha mostra os modelos em chips na ordem definida no painel e permite exceção de preço por modelo (a capa do A16 sai mais cara).

03

Carrinho de atacado

Persistente no localStorage, agrupado por produto, com o item recém-adicionado no topo. Escolha de cores com distribuição por unidade, versão masculina/feminina, conectores (ponta USB-C, Micro USB, Lightning) e frete real por CEP via SuperFrete ou retirada na loja.

04

Checkout pelo WhatsApp

POST /api/orders registra o pedido, recalcula preços a partir do banco, gera o código e devolve a URL do WhatsApp com a mensagem pronta. O consultor confere o detalhe item a item no painel; a conversa recebe só o resumo.

05

Painel do lojista

Produtos com formulário que muda conforme a categoria (uma caixa de som não pede modelo de celular), seleção em massa, upload de imagem com validação e redimensionamento, categorias, banners, depoimentos, marcas & modelos com reordenação por arrastar e configurações do site.

06

Exportação Excel e PDF sem biblioteca

Lista de pedidos (duas abas) ou pedido por pedido (folha de separação, um por página). Os dois formatos são escritos no navegador em código próprio — xref do PDF e CRC do zip cobertos por teste — para não carregar centenas de kB por um caso simples.

07

Medição Meta Pixel + Conversions API

Eventos no navegador com consentimento de cookies e deduplicação com os eventos enviados pelo servidor. O token da CAPI vive só na API; o painel mostra o estado da integração e dispara evento de teste.

08

Segurança e operação

JWT + bcrypt, perfis ADMIN/EDITOR, Zod em toda entrada, Helmet, CORS por lista, rate limit por rota, logs Pino com redação de credenciais, upload validado pelo conteúdo do arquivo e PWA do painel com página offline.


07

Telas do sistema

Capturas reais do produto, organizadas por módulo. Clique em qualquer tela para ampliar.

Hero com carrossel de banners e chamada para o catálogo
Categorias com imagem e contagem de itens
Produtos em destaque com preço a partir de e mínimo
Benefícios e chamada para montar o pedido
Formas de pagamento e marcas trabalhadas
Catálogo com filtros laterais e ordenação
Capas e Cases filtradas por Samsung → A05
Busca por nome ou marca
Categoria com filtro de conector
Ficha com chips de modelo e busca de modelo
Compre mais e economize: faixa de 200+ un
Exceção de preço por modelo destacada nos chips

08

No celular

A maior parte dos lojistas monta o pedido no celular, no balcão da própria loja — a vitrine e o painel foram desenhados primeiro para essa tela.

Home
Catálogo
Ficha
Adicionado
Carrinho
Menu
Painel · pedidos
Painel · modelos

09

Tecnologias

Front-end

React 18TypeScriptVite 6React Router 7CSS custom properties

Back-end

Node.js 20Express 4Prisma 5Zod

Banco de Dados

PostgreSQL 16

Deploy

Vercel (vitrine + painel)Railway (API + Postgres + volume)

Integrações

WhatsAppSuperFrete (frete)Meta Pixel + Conversions APIViaCEPPix BR CodeSharp (imagens)

Bibliotecas

jsonwebtokenbcryptHelmetexpress-rate-limitPinomulterqrcode-generatorPlaywright (e2e)

10

Decisões de Design

A identidade veio do protótipo original — âmbar #F7A81B sobre preto, tipografia Archivo em itálico pesado nos títulos — e foi transformada em tokens CSS reaproveitados pela vitrine e pelo painel. A escolha de cor e versão acontece no carrinho, não na ficha: escolher cor no meio de 60 chips de modelo era informação demais para a hora da compra. No celular, adicionar não abre a gaveta — sai um aviso curto com atalho e o contador pulsa — e a gaveta, quando aberta, é folha de baixo com a página visível atrás. O painel mostra só o que a categoria usa e tem atalhos ↑↓ ao lado do arrastar, pensados para quem edita do celular.

11

Desafios Técnicos

O maior desafio foi a política de preço do balcão: a faixa de desconto é do produto somando os modelos, o preço pode variar por modelo e o carrinho precisa mostrar o progresso uma vez por produto. Resolvi com aggregateQuantities e priceForLine compartilhados entre front e API, com o servidor como fonte da verdade e o navegador como espelho testado. Segundo: o catálogo chegou em PDF, sem cor, sem modelo e com nomes inconsistentes — um pipeline em Python extraiu, classificou e revisou os itens, e o painel ganhou ações em massa (opção de cor, ponta, peso e medidas) para o cliente terminar o cadastro sem abrir 349 formulários. Terceiro: exportação Excel/PDF no navegador sem biblioteca, com pedido por página, quebra de linha em vez de reticências e continuação marcada quando o pedido não cabe na folha.


12

Resultados

  • Site em produção em eacentral.com.br com 349 produtos, 14 categorias e 293 modelos de aparelho cadastrados pelo próprio cliente no painel
  • Pedidos de atacado chegam registrados e recalculados no servidor — o consultor confere no painel em vez de decifrar áudio
  • Catálogo importado do PDF original com pipeline próprio de extração e classificação, sem digitação manual
  • Cliente autônomo: preços, faixas, modelos, banners e frete são editados no painel, sem deploy

13

Aprendizados

  • Regra de preço no servidor: o navegador mostra, o banco decide. pricing.ts existe nos dois lados, com um teste que compara as duas implementações caso a caso — o total da tela é o total do pedido
  • Quatro atributos como relações de verdade (cores, faixas, compatibilidade, conectores) em vez de um EAV genérico: filtra rápido no Postgres e o painel ganha uma tela para cada, em vez de um formulário chave/valor
  • Conector modelado como conector + lado (entrada/saída), não como par fechado 'USB-A → USB-C' — um carregador 3 em 1 tem três saídas, e cadastrar um conector novo é uma linha na tabela
  • Reordenar listas grava a lista inteira numa transação: mover um item muda a posição de todos entre origem e destino, e uma requisição por linha deixaria a lista meio gravada se o 4G caísse
  • Escrever XLSX e PDF na mão vale a pena quando o caso é pequeno e bem definido — e só com teste do xref e do CRC, porque um byte errado não dá erro na geração, dá 'arquivo corrompido' na mão do lojista
  • O cliente manda pedidos por áudio e vídeo de tela; transformar isso em prompts estruturados para o desenvolvimento virou parte do processo do projeto