Files
graphs/CONTEXT.md
Cauê Faleiros 62a0bcfbc9
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 44s
docs: add project context and remove boilerplate
2026-05-27 16:18:10 -03:00

99 lines
6.9 KiB
Markdown

# Context
## 1. Project Overview
This project (often referred to as "Nexstar Graphs" or simply "Graphs") is a real-time sales and inventory dashboard. Its primary purpose is to ingest live webhook payloads from an external ERP (Tiny ERP) via n8n, securely store that data, and provide a visually rich, responsive dashboard for business analytics. It tracks total sales, product performance, customer behavior, and live inventory levels, while also providing tools for WhatsApp marketing campaigns.
## 2. Tech Stack & Tooling
**Frontend:**
* **Library:** React 19.2.5
* **Language:** TypeScript 6.0.2
* **Build Tool:** Vite 8.0.10
* **Styling:** Tailwind CSS 4.2.4
* **Icons:** Lucide React 1.14.0
* **Charts:** Recharts 3.8.1
* **Routing:** React Router DOM 7.14.2
**Backend:**
* **Environment:** Node.js
* **Framework:** Express 5.2.1
* **Database:** PostgreSQL (via `pg` 8.20.0)
* **Authentication:** JWT (`jsonwebtoken` 9.0.3)
* **CORS & Middleware:** `cors`, `body-parser`
**Infrastructure & CI/CD:**
* **Containerization:** Docker & Docker Compose
* **Proxy:** Nginx
* **CI/CD:** Gitea Actions (deploy.yml)
* **Automation:** n8n (External trigger source)
## 3. Architecture & Design Decisions
* **Decoupled Client-Server:** The frontend is a statically built SPA served by Nginx, communicating with an isolated Node.js API.
* **Idempotent Database Operations:** Due to potential retry/spam from n8n webhooks, database insertions strictly use `INSERT ... ON CONFLICT DO UPDATE SET` (UPSERTs). The backend dynamically generates fallback IDs using composite keys (`Name_Date_Value`) to prevent historical data squashing when explicit `ID_Pedido` fields are missing.
* **"Waiting Room" Debounce Pattern:** To prevent webhook spam during massive inventory updates, the `/api/stock` route intercepts payloads with large deltas (`>= 100`). It parks them in an in-memory dictionary grouped by Base Product Name, accumulates the numbers over a 30-minute setTimeout, and then executes a single aggregated webhook to N8N targeting the Top 100 buyers.
* **Smart Polling vs. SSE:** Real-time UI updates are handled via client-side polling (`setInterval`) rather than Server-Sent Events (SSE) to bypass persistent connection drops caused by production reverse proxies.
* **Client-Side Analytics:** The backend returns raw data arrays; sorting, mapping, deduplication (e.g., grouping unique orders by time), and chart metric generation are processed dynamically in the React `useMemo` hooks to reduce server load.
## 4. Directory Structure
```text
/
├── .gitea/workflows/ # CI/CD pipeline definitions
├── backend/ # Node.js Express API
│ ├── Dockerfile # Backend container definition
│ ├── index.js # Core API logic, DB initialization, and Webhook handlers
│ └── package.json
├── public/ # Static assets (Favicons)
├── src/ # React Frontend Application
│ ├── components/ # Reusable UI elements (Layout, DateRangePicker)
│ ├── pages/ # Route-level views (Dashboard, Products, Clients)
│ ├── dataService.ts # Centralized API fetch logic and JWT handling
│ ├── types.ts # Shared TypeScript interfaces
│ └── main.tsx # React entry point
├── docker-compose.yml # Local orchestration and environment variable mapping
├── nginx.conf # Production web server routing
└── vite.config.ts # Frontend build configuration
```
## 5. Core Business Rules & Domain Entities
* **Order Entity (`orders` table):** Tracks `cliente_nome`, `data_pedido`, `valor_pedido`, `produto_id`, `quantidade`, `valor_unitario`, `pedido_id`, and `cliente_fone`.
* **Stock Entity (`stock` table):** Tracks `produto_id`, `nome`, `saldo` (absolute current inventory), and `delta_estoque`. The database treats the ERP's `saldo` as the Absolute Truth (overwriting existing values rather than performing math) to prevent desynchronization.
* **WhatsApp Marketing Integration:** The system actively extracts phone numbers from incoming n8n payloads (checking `Fone_Cliente`, `fone`, or `celular`). Numbers are exposed in the UI for direct "Click-to-Chat" links and exported to CSV files for bulk marketing.
* **Filter Persistence:** User preferences for Date Ranges, Sort options, and Auto-Refresh intervals are rigidly persisted to `localStorage` to survive page reloads. The "Hoje" (Today) date preset explicitly extends to `23:59:59.999` to ensure incoming real-time webhooks remain visible on the current day's graph.
## 6. CI/CD & Deployment
* **Gitea Actions:** A workflow located in `.gitea/workflows/deploy.yml` triggers on pushes to the `main` branch.
* **Docker Registry:** The pipeline builds the `frontend` and `backend` Docker images and pushes them directly to `gitea.blyzer.com.br/blyzer/`.
* **Production Deployment:** Updates are deployed manually via Portainer by pulling the `latest` image tags from the Gitea registry and redeploying the stack.
* **Environment Variables:** Security secrets (`API_KEY`, `JWT_SECRET`, `POSTGRES_PASSWORD`, `N8N_WHATSAPP_TRIGGER_URL`) are injected via the Portainer stack configuration and passed into containers via `docker-compose.yml`.
## 7. Environment Setup & Scripts
**Running Locally:**
1. Start the database:
```bash
docker compose up -d db
```
2. Start the Backend (from `/backend`):
```bash
npm install
npm start
```
3. Start the Frontend (from project root):
```bash
npm install
npm run dev # For HMR development
npm run preview # For production build testing
```
**Building the Frontend:**
```bash
npm run build
```
## 8. Coding Standards & AI Directives
* **Strict Type Safety:** Use explicit TypeScript interfaces (defined in `types.ts`). Avoid `any` where possible. Do not bypass type checks with `// @ts-ignore`.
* **Idiomatic React:** Use functional components and hooks (`useState`, `useEffect`, `useMemo`). Complex data transformations (like merging arrays into chart-ready datasets) MUST be wrapped in `useMemo` to prevent unnecessary re-renders.
* **Tailwind Architecture:** All styling must be handled via Tailwind CSS utility classes. Avoid custom CSS files unless defining global font families or root variables in `index.css`.
* **Robust Data Handling:** Always implement graceful fallbacks for missing data. Never assume an API payload will contain all keys. (e.g., `item.id || item.ID_Pedido || ''`).
* **Database Migrations:** There is no ORM (like Prisma or Sequelize). Table schemas and indexes are managed via raw SQL statements inside the `initDB()` function in `backend/index.js` using `IF NOT EXISTS` clauses for safe startup execution.
* **API Security:** All backend modifications exposing or altering data MUST use the `verifyToken` middleware for frontend requests or `authenticateAPIKey` for external n8n webhooks.