Saltar al contenido
Sistema webCliente real2026

EA Central

E-commerce mayorista con pedidos por WhatsApp — vitrina en React, panel administrativo y API en Node/PostgreSQL

React 18TypeScriptVite 6React Router 7CSS custom propertiesNode.js 20
Funciona enWebCelular (responsivo)PWA del panel
eacentral.com.br
productos en el catálogo
349
modelos de dispositivos en 6 marcas
293
partes: vitrina, panel y API
3
de los precios recalculados en el servidor
100%

01

Visión General

EA Central Atacados es una distribuidora de electrónicos y accesorios en el Brás (São Paulo) que vendía con un catálogo en PDF y una lista por WhatsApp. El proyecto nació como un prototipo HTML de una sola página y yo lo reconstruí como una aplicación full-stack en tres partes: la vitrina en React 18 + TypeScript (Vercel), la API con Express + Prisma + PostgreSQL (Railway) y el panel administrativo, dentro del mismo front-end, donde el cliente registra productos, categorías, marcas y modelos de dispositivos, banners, pedidos y configuraciones. La regla de negocio del mayorista vive en el servidor: la tabla de precios por cantidad pertenece al producto y no al modelo — 100 láminas protectoras del A05 y 100 del iPhone 13 pagan el tramo de 200 —, y todo pedido se recalcula desde la base de datos antes de convertirse en un mensaje de WhatsApp. El catálogo se importó del PDF original con un pipeline propio de extracción y clasificación, y el sitio ya funciona en producción con pedidos reales que llegan por el panel.

Mi rol

Desarrollador full-stack en solitario — modelado del dominio, API REST con Prisma/PostgreSQL, front-end en React/TypeScript de la vitrina y del panel, importación del catálogo, integraciones (WhatsApp, SuperFrete, Meta Pixel/CAPI, Pix), despliegue en Vercel + Railway y evolución continua a partir de los pedidos del cliente.


Categoría

Sistema web

Año

2026

Estado

Cliente real

Plataformas

WebCelular (responsivo)PWA del panel

La vitrina y el panel son el mismo front-end en React; la API es la única que habla con la base de datos y la única que decide el precio. WhatsApp es el canal de cierre, no el sistema.

Vitrina + Panel

React 18 · Vercel

TypeScriptReact Router 7Vite

API REST

Express · Railway

PrismaZodJWTPino

Datos y multimedia

PostgreSQL + volumen

Postgres 16UploadsMigrations

Sincronización: POST /api/orders recalcula el pedido desde la base de datos y devuelve la URL de WhatsApp con el mensaje listo.


02

El Problema

El comerciante atendía por WhatsApp con un catálogo en PDF: el cliente mandaba la lista por audio, el asesor calculaba el precio mayorista a mano, se equivocaba de tramo de descuento y perdía pedidos en la conversación. No existía un filtro por modelo de dispositivo — el criterio principal de quien compra fundas y láminas protectoras — ni un registro de los pedidos fuera del celular del vendedor.

03 — La Solución

Una vitrina rápida, hecha para quien arma pedidos grandes: catálogo filtrado por categoría, marca y modelo de dispositivo, ficha con precio por modelo y tramos de descuento, carrito persistente con elección de colores y versión, cotización de flete por CEP (código postal brasileño) y un botón que registra el pedido en la API y abre WhatsApp con el mensaje listo. Del otro lado, un panel donde el propio cliente mantiene el catálogo y da seguimiento a los pedidos, con exportación para separar y verificar.


04

Por dentro del producto

El sistema en funcionamiento, grabado de la aplicación real con una tienda de demostración — ninguna pantalla es un mockup.

01

Precio mayorista

El tramo de descuento baja solo cuando se completa el volumen

El cliente agrega láminas protectoras de varios modelos; el carrito suma todo por producto y avisa cuánto falta para el siguiente tramo. Al pasar de 200 unidades, el precio de cada línea baja — y el servidor recalcula el pedido completo antes de generar el mensaje.

  • Tabla por producto, armada en el panel solo con la cantidad mínima de cada tramo
  • Elección de colores con distribución por unidad y versión masculina/femenina
  • Flete real por CEP (SuperFrete) o retiro en la tienda
Precio mayorista
02

Compatibilidad

Filtro por dispositivo y precio por modelo

Quien compra una funda busca por el celular, no por el nombre del producto. El catálogo filtra por marca y modelo, y la ficha muestra los modelos en chips en el orden de lanzamiento definido en el panel — con un precio distinto cuando un modelo cuesta más.

  • 293 modelos en 6 marcas, registro global y vínculo por producto
  • Orden natural (NOTE 7, NOTE 8, NOTE 8 PRO…) en lugar de alfabético
  • Excepción de precio por modelo registrada solo para los que se salen del estándar
Compatibilidad
03

Panel

Un formulario que cambia con la categoría

Una funda pide modelo de dispositivo y colores; un cable pide conector; un parlante no pide nada de eso. Tres flags en la categoría gobiernan lo que aparece, y un atajo revela la sección oculta cuando el ítem se sale de la regla.

  • Tramos de precio con el final de cada uno calculado a partir del siguiente
  • Dispositivos compatibles con búsqueda y selección por marca
  • Carga validada por el contenido, rotación corregida y reducción a 1600 px
Panel
04

Pedidos

Estado, detalle ítem por ítem y exportación para separar

Cada pedido guarda el nombre y el precio al momento de la compra. El panel muestra los ítems con modelo, colores y punta, cambia el estado con un clic y exporta el resultado del filtro a Excel o PDF — una lista para revisar el mes, o un pedido por página para separar en el depósito.

  • La exportación recorre hasta 2.000 pedidos, no solo la página cargada
  • XLSX con valores como número y fechas como fecha
  • PDF con encabezado repetido, filas alternadas y continuación marcada
Pedidos
05

Celular

Hecho para quien arma el pedido en el teléfono

Agregar no abre el cajón: aparece un aviso con un atajo y el contador pulsa. El cajón, cuando se abre desde el ícono, es una hoja inferior con la página visible detrás. En el panel, ↑ y ↓ reemplazan el arrastre para quien edita el orden de los modelos con el dedo.

  • Carrito persistente — un refresh no borra una lista de 15 productos
  • WhatsApp flotante en todas las páginas
  • PWA del panel con página offline
Celular

05

6 flujos en video

Cada video muestra una tarea completa, de principio a fin. Haz clic para verlo con controles.


06

Funcionalidades Principales

01

Precio progresivo por cantidad

Cada producto tiene su propia tabla (1–99 · 100+ · 300+). El tramo se alcanza con la suma de todos los modelos del mismo producto en el carrito, que muestra cuánto falta para el siguiente escalón. El servidor valida la tabla y lo recalcula todo en el pedido.

02

Compatibilidad marca → modelo

Registro global de 6 marcas y 293 modelos, vinculados producto por producto. El catálogo filtra por dispositivo, la ficha muestra los modelos en chips en el orden definido en el panel y permite una excepción de precio por modelo (la funda del A16 sale más cara).

03

Carrito mayorista

Persistente en localStorage, agrupado por producto, con el ítem recién agregado arriba. Elección de colores con distribución por unidad, versión masculina/femenina, conectores (punta USB-C, Micro USB, Lightning) y flete real por CEP vía SuperFrete o retiro en la tienda.

04

Checkout por WhatsApp

POST /api/orders registra el pedido, recalcula los precios desde la base de datos, genera el código y devuelve la URL de WhatsApp con el mensaje listo. El asesor revisa el detalle ítem por ítem en el panel; la conversación recibe solo el resumen.

05

Panel del comerciante

Productos con un formulario que cambia según la categoría (un parlante no pide modelo de celular), selección masiva, carga de imágenes con validación y cambio de tamaño, categorías, banners, testimonios, marcas y modelos con reordenamiento por arrastre y configuración del sitio.

06

Exportación a Excel y PDF sin librería

Lista de pedidos (dos pestañas) o pedido por pedido (hoja de separación, uno por página). Ambos formatos se escriben en el navegador con código propio — el xref del PDF y el CRC del zip cubiertos por pruebas — para no cargar cientos de kB por un caso simple.

07

Medición con Meta Pixel + Conversions API

Eventos en el navegador con consentimiento de cookies y deduplicación con los eventos enviados desde el servidor. El token de la CAPI vive solo en la API; el panel muestra el estado de la integración y dispara un evento de prueba.

08

Seguridad y operación

JWT + bcrypt, perfiles ADMIN/EDITOR, Zod en toda entrada, Helmet, CORS por lista, rate limit por ruta, logs con Pino con redacción de credenciales, carga de archivos validada por el contenido y PWA del panel con página offline.


07

Pantallas del sistema

Capturas reales del producto, organizadas por módulo. Haz clic en cualquier pantalla para ampliarla.

Hero con carrusel de banners y llamada al catálogo
Categorías con imagen y cantidad de ítems
Productos destacados con precio desde y mínimo
Beneficios y llamada para armar el pedido
Formas de pago y marcas con las que trabajamos
Catálogo con filtros laterales y ordenamiento
Fundas filtradas por Samsung → A05
Búsqueda por nombre o marca
Categoría con filtro de conector
Ficha con chips de modelo y búsqueda de modelo
Compra más y ahorra: tramo de 200+ un
Excepción de precio por modelo destacada en los chips

08

En el celular

La mayoría de los comerciantes arma el pedido en el celular, en el mostrador de su propia tienda — la vitrina y el panel se diseñaron primero para esa pantalla.

Home
Catálogo
Ficha
Agregado
Carrito
Menú
Panel · pedidos
Panel · modelos

09

Tecnologías

Front-end

React 18TypeScriptVite 6React Router 7CSS custom properties

Back-end

Node.js 20Express 4Prisma 5Zod

Base de datos

PostgreSQL 16

Despliegue

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

Integraciones

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

Bibliotecas

jsonwebtokenbcryptHelmetexpress-rate-limitPinomulterqrcode-generatorPlaywright (e2e)

10

Decisiones de Diseño

La identidad vino del prototipo original — ámbar #F7A81B sobre negro, tipografía Archivo en cursiva pesada en los títulos — y se transformó en tokens CSS reutilizados por la vitrina y el panel. La elección de color y versión ocurre en el carrito, no en la ficha: elegir color en medio de 60 chips de modelo era demasiada información para el momento de la compra. En el celular, agregar no abre el cajón — aparece un aviso corto con un atajo y el contador pulsa — y el cajón, cuando se abre, es una hoja inferior con la página visible detrás. El panel muestra solo lo que usa la categoría y tiene atajos ↑↓ junto al arrastre, pensados para quien edita desde el celular.

11

Desafíos Técnicos

El mayor desafío fue la política de precios del mostrador: el tramo de descuento pertenece al producto sumando los modelos, el precio puede variar por modelo y el carrito necesita mostrar el progreso una sola vez por producto. Lo resolví con aggregateQuantities y priceForLine compartidos entre el front-end y la API, con el servidor como fuente de verdad y el navegador como espejo probado. Segundo: el catálogo llegó en PDF, sin color, sin modelo y con nombres inconsistentes — un pipeline en Python extrajo, clasificó y revisó los ítems, y el panel ganó acciones masivas (opción de color, punta, peso y medidas) para que el cliente terminara el registro sin abrir 349 formularios. Tercero: exportación a Excel/PDF en el navegador sin librería, con un pedido por página, salto de línea en lugar de puntos suspensivos y continuación marcada cuando el pedido no cabe en la hoja.


12

Resultados

  • Sitio en producción en eacentral.com.br con 349 productos, 14 categorías y 293 modelos de dispositivos registrados por el propio cliente en el panel
  • Los pedidos mayoristas llegan registrados y recalculados en el servidor — el asesor los revisa en el panel en lugar de descifrar audios
  • Catálogo importado del PDF original con un pipeline propio de extracción y clasificación, sin digitación manual
  • Cliente autónomo: precios, tramos, modelos, banners y flete se editan en el panel, sin despliegue

13

Aprendizajes

  • Regla de precios en el servidor: el navegador muestra, la base de datos decide. pricing.ts existe en ambos lados, con una prueba que compara las dos implementaciones caso por caso — el total de la pantalla es el total del pedido
  • Cuatro atributos como relaciones de verdad (colores, tramos, compatibilidad, conectores) en lugar de un EAV genérico: filtra rápido en Postgres y el panel gana una pantalla para cada uno, en lugar de un formulario clave/valor
  • Conector modelado como conector + lado (entrada/salida), no como un par cerrado 'USB-A → USB-C' — un cargador 3 en 1 tiene tres salidas, y registrar un conector nuevo es una fila en la tabla
  • Reordenar listas guarda la lista completa en una transacción: mover un ítem cambia la posición de todos los que están entre el origen y el destino, y una solicitud por fila dejaría la lista guardada a medias si se cae el 4G
  • Escribir XLSX y PDF a mano vale la pena cuando el caso es pequeño y bien definido — y solo con pruebas del xref y del CRC, porque un byte equivocado no da error al generar, da 'archivo dañado' en manos del comerciante
  • El cliente manda los pedidos por audio y videos de pantalla; convertir eso en prompts estructurados para el desarrollo pasó a ser parte del proceso del proyecto