Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ytabeloved/ordervista/llms.txt

Use this file to discover all available pages before exploring further.

Ordervista follows a classic three-tier web architecture: a React single-page application handles all presentation logic in the browser, a Node.js/Express REST API encapsulates business logic and data access on the server, and a MySQL relational database provides persistent storage. The tiers communicate exclusively over HTTP — the browser sends JSON requests with a JWT bearer token, Express validates the token and role before dispatching to the appropriate controller, and the controller queries MySQL through parameterized statements before returning a JSON response. This separation keeps each tier independently deployable and testable.

Frontend Architecture

The frontend is a React 19 single-page application built and served by Vite. All navigation happens client-side through React Router DOM v7 — the server never performs server-side rendering. API communication is handled entirely by Axios, which is pre-configured with the base URL from VITE_API_URL. User sessions are maintained in localStorage: after a successful login, the JWT and user profile are stored there and attached as Authorization: Bearer <token> headers on every protected request.

Frontend Routes

All routes are defined in AppRoutes.jsx. Public routes (/login, /register) render directly. Every other route is wrapped in a <ProtectedRoute> component that checks for a valid token before rendering the page.
RoutePage ComponentAccess
/loginLoginPublic
/registerRegisterPublic
/DashboardAdmin (AdminLayout)
/usuariosUsersAdmin (AdminLayout)
/categoriasCategoriesAdmin (AdminLayout)
/productosProductsAdmin (AdminLayout)
/reportesReportsAdmin (AdminLayout)
/operatorOrderManagementOperator (AdminLayout)
/operator/new-orderCreateInPersonOrderOperator (AdminLayout)
/kitchenKitchenCommandsOperator (AdminLayout)
/receiptsReceiptsOperator (AdminLayout)
/menuMenuCustomer (ProtectedRoute)
/cartCartCustomer (ProtectedRoute)
/addressesAddressesCustomer (ProtectedRoute)
/ordersOrdersCustomer (ProtectedRoute)
Admin and operator routes are additionally wrapped in <AdminLayout>, which renders the shared sidebar and topbar navigation shell.

Backend Architecture

The backend is a Node.js + Express 5 API organized around the MVC pattern. The entry point is server.js, which mounts all route modules and starts the HTTP listener. Application-level configuration (CORS, JSON parsing, core routes) lives in src/app.js.

Directory Structure

backend/
├── server.js               # Entry point — mounts routes, starts server
└── src/
    ├── app.js              # Express app config, core middleware, base routes
    ├── config/
    │   └── schema.sql      # MySQL schema definition
    ├── controllers/        # Request handlers — parse req, call model, send res
    ├── middleware/
    │   ├── verifyToken.js  # JWT validation middleware
    │   └── authorizeRoles.js # Role-based access control middleware
    ├── models/             # Database query functions (mysql2)
    └── routes/             # Express routers — one file per resource

API Route Modules

Each resource is handled by a dedicated Express router registered under /api:
/api/health          → inline handler in server.js
/api/auth            → authRoutes
/api/users           → userRoutes
/api/categories      → categoryRoutes
/api/products        → productRoutes
/api/menu            → menuRoutes
/api/orders          → orderRoutes
/api/order-types     → orderTypeRoutes
/api/commands        → commandRoutes
/api/addresses       → addressRoutes
/api/reports         → reportRoutes

Authentication and Authorization Middleware

Protected routes use two middleware layers applied in sequence:
// 1. verifyToken — validates the JWT in the Authorization header
router.get("/protected-resource", verifyToken, authorizeRoles(1, 2), controller.handler);

// 2. authorizeRoles — checks that req.user.id_rol is in the allowed list
//    Role IDs: 1 = Administrator, 2 = Operator, 3 = Customer
  • verifyToken — Extracts the Bearer token from the Authorization header, verifies it against JWT_SECRET, and attaches the decoded payload to req.user. Requests with missing or invalid tokens receive a 401 Unauthorized response.
  • authorizeRoles(...roles) — Receives one or more role IDs. After verifyToken runs, it compares req.user.id_rol against the allowed list and returns 403 Forbidden if the role is not permitted.
Role ID reference:
id_rolRole LabelAccess Level
1AdministratorFull system access
2OperatorOrder and kitchen management
3CustomerMenu, cart, and personal orders

Database Schema

Ordervista uses a MySQL relational schema with 10 tables. Foreign key relationships enforce referential integrity across the entire order lifecycle. Table names are uppercase to ensure consistent behavior on case-sensitive Linux database hosts.

Tables and Relationships

ROLES
  └── id_rol (PK)

USUARIOS
  ├── id_usuario (PK)
  └── id_rol → ROLES.id_rol

DIRECCIONES
  ├── id_direccion (PK)
  └── id_usuario → USUARIOS.id_usuario

CATEGORIAS
  └── id_categoria (PK)

PRODUCTOS
  ├── id_producto (PK)
  └── id_categoria → CATEGORIAS.id_categoria

TIPOS_PEDIDO
  └── id_tipo_pedido (PK)

ESTADOS_PEDIDO
  └── id_estado (PK)

PEDIDOS
  ├── id_pedido (PK)
  ├── id_usuario   → USUARIOS.id_usuario
  ├── id_tipo_pedido → TIPOS_PEDIDO.id_tipo_pedido
  ├── id_direccion → DIRECCIONES.id_direccion (nullable — in-person orders)
  └── id_estado    → ESTADOS_PEDIDO.id_estado

DETALLE_PEDIDO
  ├── id_detalle (PK)
  ├── id_pedido  → PEDIDOS.id_pedido
  └── id_producto → PRODUCTOS.id_producto

COMANDAS
  ├── id_comanda (PK)
  └── id_pedido  → PEDIDOS.id_pedido (UNIQUE — one comanda per order)
Key design decisions:
  • PEDIDOS.id_direccion is nullable so that in-person (operator-created) orders do not require a delivery address.
  • COMANDAS.id_pedido has a UNIQUE constraint, enforcing a one-to-one relationship between an order and its kitchen command ticket.
  • activo boolean flags on USUARIOS, CATEGORIAS, PRODUCTOS, and DIRECCIONES enable soft-deletion without breaking foreign key references.

Request Flow

The following steps trace the journey of a typical authenticated API request — for example, an operator fetching the active order list from GET /api/orders.
1

Client initiates request

The React component calls an Axios service function. Axios attaches the JWT stored in localStorage as the Authorization: Bearer <token> header and dispatches the HTTP request to VITE_API_URL.
// Example Axios call from a frontend service
axios.get("/orders", {
  headers: { Authorization: `Bearer ${localStorage.getItem("token")}` }
});
2

Express router receives the request

server.js receives the request and matches it to the /api/orders router. The router passes the request down its middleware chain before invoking the controller.
// server.js
app.use("/api/orders", orderRoutes);
3

verifyToken middleware runs

verifyToken extracts the bearer token, calls jwt.verify() against JWT_SECRET, and — if valid — attaches the decoded payload (including id_usuario and id_rol) to req.user. An invalid or missing token immediately returns 401 Unauthorized.
4

authorizeRoles middleware runs

authorizeRoles checks that req.user.id_rol is in the set of roles permitted for this route. If the role is not authorized, the middleware returns 403 Forbidden before the controller is ever called.
5

Controller handles the request

The controller function receives the validated req object, extracts any query parameters or body fields, and calls the appropriate model function.
6

Model queries MySQL

The model executes a parameterized SQL query through the mysql2 connection pool and returns the result rows to the controller.
7

Response returned to the client

The controller formats the data as JSON and calls res.json(). Express serializes the response and sends it back over HTTP. The React component receives the data, updates state, and re-renders the UI.

Build docs developers (and LLMs) love