Skip to content

Frontend - Portal de Clientes

Frontend PWA independiente para clientes finales, completamente separado del sistema administrativo.

Caracteristicas

  • Tecnologia: Vite + React 19 + TypeScript
  • Repositorio: Independiente (portal-usuarios submodule en /var/www/Bautista/portal-usuarios/)
  • Optimizado para: Clientes finales en dispositivos moviles (mobile-first)
  • PWA: vite-plugin-pwa, Service Workers, offline support, installable
  • Despliegue: Docker por tenant (build multi-stage: Node build, nginx:alpine serve)
  • Build por tenant: Cada imagen Docker compila con variables VITE_* propias del tenant (branding, URLs, credenciales)
  • Branding: CSS variables customizables por tenant via shadcn/ui + Tailwind CSS
  • Autenticacion: JWT con password (registro, login, reset de password)

Stack Tecnologico

CategoriaTecnologiaJustificacion
BuildViteBuild estatico, HMR instantaneo, PWA plugin oficial
UI FrameworkReact 19 + TypeScriptComponentes modernos con hooks, ecosistema maduro
UI Libraryshadcn/ui + Radix UIComponentes headless, altamente customizables via CSS variables. Ideal para branding por tenant
StylingTailwind CSSUtility-first, responsive por defecto, purge automatico. Mobile-first con breakpoints sm, md, lg
RouterTanStack RouterType-safe routing con validacion de search params via Zod
Server StateTanStack QueryCache, refetch automatico, polling via refetchInterval para actualizaciones en tiempo real
Client StateReact ContextSolo para auth (JWT) y branding (VITE_* env vars). Sin store global
FormsReact Hook Form + ZodValidacion declarativa con schemas tipados, rendimiento con register sin re-renders
HTTPAxiosConsistente con bautista-app admin, interceptors para JWT y tenant headers
PWAvite-plugin-pwaService worker con Workbox, manifest generado desde config, precaching automatico
TestingVitest + Testing LibraryUnit y componentes: renderizado, interacciones, hooks
E2EPlaywrightFlujos criticos: login, registro, pago

Documentacion

Arquitectura Frontend

Arquitectura completa del frontend PWA, stack tecnologico, estructura de proyecto y componentes.

Incluye:

  • Stack tecnico completo (Vite, React 19, TypeScript, shadcn/ui, Tailwind, TanStack Router/Query)
  • Arquitectura de componentes con diagramas Mermaid
  • Estructura de proyecto detallada
  • Contextos (AuthContext con JWT, BrandingContext con CSS variables)
  • TanStack Router: route tree type-safe con todas las paginas
  • TanStack Query: configuracion, polling con refetchInterval
  • React Hook Form + Zod: schemas de validacion
  • shadcn/ui: patrones de uso de componentes
  • API Client (Axios con interceptors para JWT y tenant headers)
  • PDF cupon: proxy via backend (GET /portal/cupones/{id}/pdf)
  • PWA: vite-plugin-pwa, service worker, manifest
  • Mobile-first responsive patterns
  • Testing strategy (Vitest+TL vs Playwright)

Paginas

Documentacion de cada pagina del portal:

  • /login - Login con DNI/CUIT + password
  • /register - Auto-registro con validacion contra ordcon
  • /forgot-password - Solicitar codigo de reset via email
  • /reset-password - Ingresar codigo + nueva password
  • /dashboard - Resumen de cuenta (saldo, facturas vencidas, ultimo pago)
  • /deudas - Listado de deudas pendientes con indicadores de vencimiento
  • /pagar - Seleccion de facturas y pago online
  • /pagar/exito, /pagar/error, /pagar/pendiente - Resultado de pago (con polling automatico)
  • /cupones - Listado y generacion de cupones con codigo de barras
  • /historial-pagos - Historial de transacciones

Componentes

Componentes reutilizables del portal:

  • Layout: Header, Footer, Navigation (shadcn/ui + Tailwind responsive)
  • Auth: LoginForm, RegisterForm, ForgotPasswordForm, ResetPasswordForm (React Hook Form + Zod)
  • Deudas: DeudaCard, DeudaList
  • Pagos: PaymentButton, SelectFacturas
  • Cupones: CuponCard, CuponList, descarga PDF via proxy
  • UI (shadcn/ui): Button, Card, Input, Form, Dialog, Badge, Skeleton, Toast

API Client

Cliente de comunicacion con el backend:

  • Configuracion Axios con VITE_BACKEND_URL
  • Headers automaticos: Authorization (JWT Bearer), X-Tenant-ID, X-Sucursal-ID
  • Interceptors: request (JWT + tenant context), response (401 -> refresh token -> retry o redirect a login)
  • Modulos por recurso: auth, ctacte, pagos, cupones
  • TanStack Query hooks: useDeudas, usePagos, useCupones, useMiCuenta

PWA

Configuracion Progressive Web App con vite-plugin-pwa:

  • Service Worker via Workbox (generateSW)
  • Manifest generado desde vite.config.ts con variables VITE_*
  • Cache strategies: NetworkFirst (API), CacheFirst (assets), StaleWhileRevalidate (fuentes)
  • Precaching automatico de shell de la app

PDF Cupones

La descarga de PDF de cupones se realiza via proxy del backend:

  • Frontend llama a GET /portal/cupones/{id}/pdf
  • Backend recibe el request, resuelve tenant, y llama internamente al servicio de informes (puerto 9999)
  • Backend retorna el PDF como stream (Content-Type: application/pdf)
  • El cliente NUNCA ve ni accede directamente al servicio de informes

Polling para Actualizaciones en Tiempo Real

En vez de WebSockets o SSE, se usa polling automatico con TanStack Query:

  • refetchInterval: 5000 (5 segundos) en paginas de resultado de pago (/pagar/exito, /pagar/pendiente)
  • refetchInterval: 10000 (10 segundos) en pagina de deudas (si hay pagos recientes pendientes de acreditacion)
  • El polling se desactiva automaticamente cuando la ventana pierde foco (refetchIntervalInBackground: false)
  • Sin infraestructura adicional: no se necesita servidor WebSocket ni eventos del servidor

Diseno Mobile-First

El portal esta optimizado para uso desde celulares. Los clientes principalmente consultan deudas y pagan desde sus telefonos.

Patron de breakpoints Tailwind:

  • Default: mobile (320px+)
  • sm: tabletas pequenas (640px+)
  • md: tabletas (768px+)
  • lg: desktop (1024px+)

Principios:

  • Cards apiladas verticalmente en mobile, grid en desktop
  • Botones full-width en mobile, auto-width en desktop
  • Navegacion inferior en mobile, sidebar en desktop
  • Touch targets minimo 44x44px
  • Sin hover-only interactions

Build por Tenant

Cada tenant recibe su propia imagen Docker con configuracion integrada en build time:

dockerfile
ARG VITE_BACKEND_URL
ARG VITE_TENANT_ID
ARG VITE_SUCURSAL_ID
ARG VITE_APP_NAME
ARG VITE_LOGO_URL
ARG VITE_PRIMARY_COLOR
ARG VITE_THEME_COLOR

Las variables VITE_* son resueltas por Vite en build time via import.meta.env. No existe inyeccion de configuracion en runtime. Cambiar la configuracion de un tenant requiere un nuevo build de la imagen Docker.

Por que build per tenant (no runtime):

  • Las variables VITE_* son build-time only por diseno de Vite
  • Simplicidad: no hay logica de inyeccion de config al iniciar el contenedor
  • Cada imagen es inmutable y reproducible
  • El costo de build es bajo (< 1 minuto por tenant con cache de Docker layers)

Branding via Variables de Entorno

Cada instancia Docker tiene su propio branding compilado en la imagen:

VariableDescripcionUso
VITE_APP_NAMENombre de la aplicacionHeader, manifest PWA, <title>
VITE_LOGO_URLURL del logoHeader, login, manifest icons
VITE_PRIMARY_COLORColor principal (hex)CSS variable --primary, shadcn/ui theme
VITE_THEME_COLORColor del tema PWAManifest, <meta name="theme-color">

shadcn/ui facilita el theming por tenant porque sus componentes se estilizan via CSS variables de Tailwind. El BrandingContext lee import.meta.env al iniciar y aplica las variables CSS en document.documentElement.

Autenticacion

  • JWT con password (no passwordless)
  • Registro automatico: DNI/CUIT debe coincidir con ordcon
  • Login: DNI/CUIT + password
  • Reset de password via codigo por email
  • AuthContext gestiona estado de autenticacion, tokens JWT y refresh
  • Access token en localStorage (SPA sin backend propio, no hay httpOnly cookies disponibles)
  • Refresh token UUID almacenado en portal_users del backend

Testing

TipoHerramientaAlcance
ComponentesVitest + Testing LibraryRender, interacciones, hooks, forms, contexts
E2EPlaywrightFlujos criticos: login, registro, pago online, resultado de pago

Vitest + Testing Library: Tests rapidos en memoria (jsdom). Cubren render de componentes, validaciones de formularios (Zod schemas), comportamiento de hooks (useAuth, useDeudas), y logica de contextos.

Playwright: Tests de integracion de punta a punta en navegador real. Cubren los flujos criticos que involucran multiples paginas y comunicacion con backend: registro completo, login + ver deudas, flujo de pago hasta redireccion a gateway.

Ver tambien