From fab638080db632a0a47a4bc60521326b4ced65ea Mon Sep 17 00:00:00 2001 From: rckrdmrd Date: Tue, 20 Jan 2026 02:27:40 -0600 Subject: [PATCH] [MCH] docs: Add frontend components catalog - Create COMPONENTES-FRONTEND.md with detailed documentation of all 17 components - Document 3 reusable components: Layout, ClabeDisplay, CodiQR - Document 14 page components with props, hooks, dependencies, and line counts - Update FRONTEND_INVENTORY.yml with expanded component details - Update _INDEX.yml to include new documentation file Co-Authored-By: Claude Opus 4.5 --- docs/_definitions/COMPONENTES-FRONTEND.md | 518 ++++++++++++++++++ docs/_definitions/_INDEX.yml | 15 +- .../inventarios/FRONTEND_INVENTORY.yml | 85 ++- 3 files changed, 607 insertions(+), 11 deletions(-) create mode 100644 docs/_definitions/COMPONENTES-FRONTEND.md diff --git a/docs/_definitions/COMPONENTES-FRONTEND.md b/docs/_definitions/COMPONENTES-FRONTEND.md new file mode 100644 index 000000000..c4b9768c0 --- /dev/null +++ b/docs/_definitions/COMPONENTES-FRONTEND.md @@ -0,0 +1,518 @@ +# Catalogo de Componentes Frontend - MiChangarrito + +**Version:** 1.0.0 +**Actualizado:** 2026-01-20 +**Framework:** React 19.2.0 + TypeScript +**Bundler:** Vite 7.2.4 +**Estilos:** TailwindCSS 4.1.18 + +--- + +## Indice + +1. [Resumen Ejecutivo](#resumen-ejecutivo) +2. [Componentes de Layout](#componentes-de-layout) +3. [Componentes de Pagos](#componentes-de-pagos) +4. [Paginas](#paginas) + - [Autenticacion](#autenticacion) + - [Dashboard y Operaciones](#dashboard-y-operaciones) + - [Finanzas](#finanzas) + - [Marketplace y Extras](#marketplace-y-extras) +5. [Contexts](#contexts) +6. [Servicios API](#servicios-api) + +--- + +## Resumen Ejecutivo + +| Metrica | Valor | +|---------|-------| +| Total Componentes Reutilizables | 3 | +| Total Paginas | 14 | +| Total Contexts | 1 (AuthContext) | +| Total Lineas de Codigo (aprox) | ~5,500 | + +--- + +## Componentes de Layout + +### Layout.tsx + +- **Archivo:** `src/components/Layout.tsx` +- **Lineas:** 178 +- **Descripcion:** Layout principal de la aplicacion con sidebar responsive y navegacion completa. +- **Props:** Ninguna (usa `` de react-router-dom) +- **Estado interno:** + - `sidebarOpen: boolean` - Control de sidebar mobile +- **Hooks usados:** + - `useState` - Estado del sidebar + - `useNavigate` - Navegacion programatica + - `useAuth` - Contexto de autenticacion +- **Dependencias:** + - `react-router-dom` (Outlet, NavLink, useNavigate) + - `lucide-react` (16 iconos: LayoutDashboard, Package, ShoppingCart, Users, CreditCard, Boxes, Settings, Menu, X, Store, LogOut, Gift, FileText, Truck, Coins, QrCode) + - `clsx` - Clases condicionales + - `AuthContext` - Usuario y logout +- **Funcionalidades:** + - Sidebar fijo en desktop (lg:) + - Sidebar overlay en mobile con backdrop oscuro + - Navegacion a 12 rutas principales + - Avatar con iniciales del tenant + - Boton de logout + - Header mobile con hamburger menu + +--- + +## Componentes de Pagos + +### ClabeDisplay.tsx + +- **Archivo:** `src/components/payments/ClabeDisplay.tsx` +- **Lineas:** 113 +- **Descripcion:** Muestra y permite copiar la CLABE virtual del tenant para recibir transferencias SPEI. +- **Props:** + - `showCreateButton?: boolean` - Mostrar boton para crear CLABE (default: true) + - `beneficiaryName?: string` - Nombre del beneficiario +- **Estado interno:** + - `copied: boolean` - Indica si se copio la CLABE +- **Hooks usados:** + - `useState` - Estado de copiado + - `useQuery` - Fetch de CLABE existente + - `useMutation` - Creacion de CLABE + - `useQueryClient` - Invalidacion de cache +- **Dependencias:** + - `@tanstack/react-query` (useQuery, useMutation, useQueryClient) + - `lucide-react` (Copy, Check, Building) + - `codiSpeiApi` - API de CoDi/SPEI +- **Funcionalidades:** + - Mostrar CLABE formateada (XXX XXX XXXX XXXX XXXX) + - Copiar al clipboard con feedback visual + - Crear CLABE virtual si no existe + - Estados de loading y vacio + +### CodiQR.tsx + +- **Archivo:** `src/components/payments/CodiQR.tsx` +- **Lineas:** 168 +- **Descripcion:** Genera y muestra QR de cobro CoDi con temporizador de expiracion. +- **Props:** + - `amount: number` - Monto a cobrar (requerido) + - `description?: string` - Descripcion del cobro + - `saleId?: string` - ID de venta asociada + - `onSuccess?: () => void` - Callback al confirmar pago + - `onCancel?: () => void` - Callback al cancelar +- **Estado interno:** + - `transactionId: string | null` - ID de transaccion generada + - `timeLeft: number` - Segundos restantes (inicia en 300) +- **Hooks usados:** + - `useState` - Estado del QR y timer + - `useEffect` - Generacion automatica y countdown + - `useMutation` - Generar QR + - `useQuery` - Polling del estado (cada 3s) +- **Dependencias:** + - `@tanstack/react-query` + - `lucide-react` (QrCode, Clock, Check, X, RefreshCw) + - `codiSpeiApi` - API de CoDi/SPEI +- **Funcionalidades:** + - Genera QR automaticamente al montar + - Countdown de 5 minutos + - Polling cada 3 segundos para verificar pago + - Estados: loading, confirmado, expirado + - Regenerar QR + +--- + +## Paginas + +### Autenticacion + +#### Login.tsx + +- **Archivo:** `src/pages/Login.tsx` +- **Lineas:** 104 +- **Descripcion:** Pagina de inicio de sesion con telefono y PIN. +- **Props:** Ninguna (export default) +- **Estado interno:** + - `phone: string` - Telefono (10 digitos) + - `pin: string` - PIN (4-6 digitos) + - `error: string` - Mensaje de error + - `isLoading: boolean` - Estado de carga +- **Hooks usados:** + - `useState` - Estados del formulario + - `useNavigate` - Redireccion post-login + - `useAuth` - Funcion login +- **Dependencias:** + - `react-router-dom` (useNavigate, Link) + - `AuthContext` - Autenticacion +- **Validaciones:** + - Telefono: 10 digitos numericos + - PIN: 4-6 digitos numericos +- **Ruta:** `/login` (publica) + +#### Register.tsx + +- **Archivo:** `src/pages/Register.tsx` +- **Lineas:** 242 +- **Descripcion:** Pagina de registro de nuevos negocios. +- **Props:** Ninguna (export default) +- **Estado interno:** + - `formData: object` - Datos del formulario completo + - `error: string` - Mensaje de error + - `isLoading: boolean` - Estado de carga +- **Hooks usados:** + - `useState` - Estados del formulario + - `useNavigate` - Redireccion post-registro + - `useAuth` - Funcion register +- **Dependencias:** + - `react-router-dom` (useNavigate, Link) + - `AuthContext` - Autenticacion +- **Campos del formulario:** + - `name` - Nombre del negocio (requerido) + - `ownerName` - Nombre del propietario (requerido) + - `businessType` - Tipo de negocio (select) + - `phone` - Telefono 10 digitos (requerido) + - `pin` - PIN 4-6 digitos (requerido) + - `confirmPin` - Confirmacion de PIN (requerido) + - `email` - Email (opcional) +- **Tipos de negocio:** tiendita, fonda, taqueria, tortilleria, verduleria, otro +- **Ruta:** `/register` (publica) + +--- + +### Dashboard y Operaciones + +#### Dashboard.tsx + +- **Archivo:** `src/pages/Dashboard.tsx` +- **Lineas:** 270 +- **Descripcion:** Panel principal con metricas, pedidos recientes y alertas de stock. +- **Estado interno:** Ninguno (todo via React Query) +- **Hooks usados:** + - `useQuery` (x3) - Stats, pedidos recientes, stock bajo +- **Dependencias:** + - `@tanstack/react-query` + - `lucide-react` (TrendingUp, ShoppingCart, Users, CreditCard, Package, AlertCircle, Loader2) + - APIs: dashboardApi, ordersApi, inventoryApi +- **Secciones:** + - Grid de 4 tarjetas de estadisticas + - Pedidos recientes (ultimos 5) + - Alertas de stock bajo +- **Componentes internos:** + - `LoadingSpinner` - Indicador de carga + - `ErrorMessage` - Mensaje de error +- **Ruta:** `/dashboard` + +#### Products.tsx + +- **Archivo:** `src/pages/Products.tsx` +- **Lineas:** 512 +- **Descripcion:** Catalogo CRUD de productos con busqueda y filtrado por categoria. +- **Estado interno:** + - `search: string` - Termino de busqueda + - `category: string` - Filtro de categoria + - `showModal: boolean` - Modal crear/editar + - `editingProduct: Product | null` - Producto en edicion + - `deletingProduct: Product | null` - Producto a eliminar + - `formData: ProductFormData` - Datos del formulario + - `formError: string | null` - Error del formulario +- **Hooks usados:** + - `useState` (x7) - Estados del CRUD + - `useQuery` - Lista de productos + - `useMutation` (x3) - Create, update, delete + - `useQueryClient` - Invalidacion +- **Dependencias:** + - `@tanstack/react-query` + - `lucide-react` (Search, Plus, Edit, Trash2, Package, X, AlertCircle, Loader2) + - `productsApi` +- **Categorias:** bebidas, botanas, lacteos, panaderia, limpieza, abarrotes, otros +- **Ruta:** `/products` + +#### Orders.tsx + +- **Archivo:** `src/pages/Orders.tsx` +- **Lineas:** 250 +- **Descripcion:** Gestion de pedidos con flujo de estados. +- **Estado interno:** + - `filter: string` - Filtro de estado +- **Hooks usados:** + - `useState` - Filtro + - `useQuery` (x2) - Pedidos filtrados y todos + - `useMutation` - Cambio de estado + - `useQueryClient` - Invalidacion +- **Dependencias:** + - `@tanstack/react-query` + - `lucide-react` (Clock, CheckCircle, XCircle, ChefHat, Package, Loader2, AlertCircle, RefreshCw) + - `clsx` + - `ordersApi` +- **Estados de pedido:** pending, confirmed, preparing, ready, completed, cancelled +- **Flujo:** pending -> confirmed -> preparing -> ready -> completed +- **Ruta:** `/orders` + +#### Customers.tsx + +- **Archivo:** `src/pages/Customers.tsx` +- **Lineas:** 390 +- **Descripcion:** Directorio de clientes con CRUD y balance de fiado. +- **Estado interno:** + - `search: string` - Busqueda + - `isModalOpen: boolean` - Modal crear/editar + - `editingCustomer: Customer | null` + - `formData: CustomerFormData` + - `formError: string | null` +- **Hooks usados:** + - `useState` (x5) + - `useQuery` - Lista clientes + - `useMutation` (x2) - Create, update + - `useQueryClient` +- **Dependencias:** + - `@tanstack/react-query` + - `lucide-react` (Search, Plus, Phone, Mail, MapPin, CreditCard, X, Loader2, AlertCircle, Edit2) + - `customersApi` +- **Informacion mostrada:** nombre, telefono, email, direccion, compras, total gastado, fiado +- **Ruta:** `/customers` + +#### Inventory.tsx + +- **Archivo:** `src/pages/Inventory.tsx` +- **Lineas:** 357 +- **Descripcion:** Control de existencias con movimientos y alertas. +- **Estado interno:** + - `showLowStock: boolean` - Toggle filtro stock bajo +- **Hooks usados:** + - `useState` + - `useQuery` (x4) - Productos, movimientos, stock bajo, alertas +- **Dependencias:** + - `@tanstack/react-query` + - `lucide-react` (Package, TrendingUp, TrendingDown, AlertTriangle, Plus, Minus, Loader2, AlertCircle, RefreshCw) + - `clsx` + - APIs: productsApi, inventoryApi +- **Secciones:** + - Banner de alertas + - Cards de resumen (unidades, valor, stock bajo) + - Tabla de inventario con barras de progreso + - Movimientos recientes +- **Ruta:** `/inventory` + +--- + +### Finanzas + +#### Fiado.tsx + +- **Archivo:** `src/pages/Fiado.tsx` +- **Lineas:** 660 +- **Descripcion:** Gestion de cuentas de credito con pagos y recordatorios. +- **Estado interno:** + - `filter: 'all' | 'pending' | 'overdue'` - Filtro + - `showNewFiadoModal: boolean` + - `showPaymentModal: boolean` + - `selectedFiado: Fiado | null` +- **Hooks usados:** + - `useState` (x4) + - `useMemo` (x3) - Stats, filtrado, pagos recientes + - `useQuery` (x2) - Fiados, clientes + - `useMutation` (x2) - Crear fiado, registrar pago + - `useQueryClient` +- **Dependencias:** + - `@tanstack/react-query` + - `lucide-react` (CreditCard, AlertTriangle, CheckCircle, Clock, Plus, Loader2, X, DollarSign) + - `clsx` + - APIs: fiadosApi, customersApi +- **Componentes internos:** + - `NewFiadoModal` - Crear nuevo fiado + - `PaymentModal` - Registrar pago +- **Ruta:** `/fiado` + +#### CodiSpei.tsx + +- **Archivo:** `src/pages/CodiSpei.tsx` +- **Lineas:** 450 +- **Descripcion:** Cobros via CoDi (QR) y SPEI (CLABE virtual). +- **Estado interno:** + - `activeTab: 'codi' | 'spei'` + - `qrAmount: string` + - `qrDescription: string` + - `copied: boolean` +- **Hooks usados:** + - `useState` (x4) + - `useQuery` (x4) - Transacciones CoDi, info SPEI, transacciones SPEI + - `useMutation` (x2) - Generar QR, crear CLABE + - `useQueryClient` +- **Dependencias:** + - `@tanstack/react-query` + - `lucide-react` (QrCode, CreditCard, Copy, Check, Clock, ArrowDownLeft, RefreshCw, Plus, Smartphone) + - `codiSpeiApi` +- **Tabs:** + - CoDi: Generar QR, historial de cobros + - SPEI: Card con CLABE, historial de transferencias +- **Ruta:** `/codi-spei` + +#### Invoices.tsx + +- **Archivo:** `src/pages/Invoices.tsx` +- **Lineas:** 668 +- **Descripcion:** Facturacion electronica CFDI 4.0 con timbrado y envio. +- **Estado interno:** + - `filter: string` - Filtro de estado + - `showConfig: boolean` - Modal configuracion + - `showNewInvoice: boolean` - Modal nueva factura +- **Hooks usados:** + - `useState` (x3) + - `useQuery` (x3) - Facturas, resumen, config fiscal + - `useMutation` (x2) - Timbrar, enviar + - `useQueryClient` +- **Dependencias:** + - `@tanstack/react-query` + - `lucide-react` (FileText, Send, XCircle, CheckCircle, Clock, Download, Plus, Settings, AlertCircle) + - `clsx` + - `invoicesApi` +- **Componentes internos:** + - `TaxConfigModal` - Configuracion fiscal (RFC, regimen, PAC) + - `NewInvoiceModal` - Crear factura con conceptos +- **Estados factura:** draft, pending, stamped, sent, cancelled +- **Ruta:** `/invoices` + +#### Tokens.tsx + +- **Archivo:** `src/pages/Tokens.tsx` +- **Lineas:** 329 +- **Descripcion:** Tienda de tokens para servicios premium con Stripe checkout. +- **Estado interno:** + - `selectedPackage: string | null` +- **Hooks usados:** + - `useState` + - `useQuery` (x3) - Balance, paquetes, historial + - `useMutation` - Compra con redirect a Stripe +- **Dependencias:** + - `@tanstack/react-query` + - `lucide-react` (Coins, Package, TrendingUp, Clock, Check, ShoppingCart, MessageSquare, FileText, Sparkles) + - `billingApi` +- **Secciones:** + - Card de balance con gradiente + - Grid de costos por servicio + - Grid de paquetes de tokens + - Historial de uso +- **Ruta:** `/tokens` + +--- + +### Marketplace y Extras + +#### Marketplace.tsx + +- **Archivo:** `src/pages/Marketplace.tsx` +- **Lineas:** 731 +- **Descripcion:** Marketplace B2B para comprar a proveedores. +- **Estado interno:** + - `view: 'suppliers' | 'orders' | 'favorites'` + - `selectedCategory: string | null` + - `searchQuery: string` + - `selectedSupplier: any` + - `showCart: boolean` + - `cart: { product, quantity }[]` +- **Hooks usados:** + - `useState` (x6) + - `useQuery` (x3) - Proveedores, ordenes, favoritos + - `useMutation` - Crear orden + - `useQueryClient` +- **Dependencias:** + - `@tanstack/react-query` + - `lucide-react` (Store, Search, Star, Heart, ShoppingCart, Package, Truck, Clock, CheckCircle, XCircle, MapPin, Phone, ChevronRight) + - `clsx` + - `marketplaceApi` +- **Componentes internos:** + - `SupplierCard` - Tarjeta de proveedor + - `OrderCard` - Tarjeta de orden + - `SupplierDetailModal` - Detalle con productos + - `CartModal` - Carrito de compras +- **Categorias:** bebidas, botanas, lacteos, pan, abarrotes, limpieza +- **Ruta:** `/marketplace` + +#### Referrals.tsx + +- **Archivo:** `src/pages/Referrals.tsx` +- **Lineas:** 271 +- **Descripcion:** Sistema de referidos con codigo unico y recompensas. +- **Estado interno:** + - `copied: boolean` +- **Hooks usados:** + - `useState` + - `useQuery` (x2) - Stats, lista de referidos +- **Dependencias:** + - `@tanstack/react-query` + - `lucide-react` (Gift, Users, Copy, Share2, Check, Clock, X) + - `referralsApi` +- **Secciones:** + - Card de compartir con codigo + - Grid de estadisticas + - Como funciona (3 pasos) + - Lista de referidos +- **Ruta:** `/referrals` + +#### Settings.tsx + +- **Archivo:** `src/pages/Settings.tsx` +- **Lineas:** 166 +- **Descripcion:** Configuracion del negocio (mock data - pendiente API). +- **Estado interno:** Ninguno (formularios no controlados) +- **Hooks usados:** Ninguno +- **Dependencias:** + - `lucide-react` (Store, CreditCard, Bell, MessageSquare, Shield) +- **Secciones:** + - Informacion del negocio + - Configuracion de fiado + - WhatsApp Business + - Notificaciones + - Plan de suscripcion +- **Estado:** MOCK DATA - Pendiente implementar endpoints backend +- **Ruta:** `/settings` + +--- + +## Contexts + +### AuthContext + +- **Archivo:** `src/contexts/AuthContext.tsx` +- **Lineas:** ~120 +- **Descripcion:** Gestion de autenticacion y sesion del usuario. +- **Provee:** + - `user: User | null` - Usuario autenticado + - `tenant: Tenant | null` - Tenant/negocio + - `isAuthenticated: boolean` - Estado de autenticacion + - `isLoading: boolean` - Cargando sesion + - `login(phone, pin): Promise` - Iniciar sesion + - `register(data): Promise` - Registrar negocio + - `logout(): void` - Cerrar sesion +- **Persistencia:** localStorage (accessToken, refreshToken, user, tenant) + +--- + +## Servicios API + +### lib/api.ts + +- **Archivo:** `src/lib/api.ts` +- **Lineas:** ~400 +- **Descripcion:** Cliente Axios con todos los endpoints agrupados. + +**Grupos de API:** + +| Grupo | Endpoints | +|-------|-----------| +| `authApi` | register, login, refresh, changePin | +| `productsApi` | getAll, getById, create, update, delete | +| `ordersApi` | getAll, getById, create, updateStatus | +| `customersApi` | getAll, getById, create, update, getFiado | +| `inventoryApi` | getMovements, createMovement, getLowStock, getAlerts | +| `dashboardApi` | getStats, getSalesChart, getTopProducts | +| `fiadosApi` | getAll, getPending, create, pay, cancel | +| `invoicesApi` | getAll, getSummary, getTaxConfig, saveTaxConfig, create, stamp, send, cancel, download | +| `marketplaceApi` | getSuppliers, getSupplierProducts, getOrders, createOrder, getFavorites, addFavorite | +| `referralsApi` | getStats, getMyReferrals, generateCode, validateCode | +| `billingApi` | getTokenBalance, getTokenPackages, getTokenUsage, purchaseTokens | +| `codiSpeiApi` | getClabe, createClabe, generateQr, getCodiStatus, getCodiTransactions, getSpeiTransactions | + +**Interceptores:** +- **Request:** Agrega Bearer token automaticamente +- **Response:** Maneja 401, intenta refresh token, limpia localStorage si falla diff --git a/docs/_definitions/_INDEX.yml b/docs/_definitions/_INDEX.yml index cd8c1eeaf..413e1386e 100644 --- a/docs/_definitions/_INDEX.yml +++ b/docs/_definitions/_INDEX.yml @@ -89,6 +89,17 @@ definiciones_locales: sprints: 7 timeline_estimado: "16 semanas" + componentes_frontend: + archivo: "COMPONENTES-FRONTEND.md" + alias: "@MCH_COMPONENTES" + descripcion: "Catalogo detallado de componentes del frontend" + validado: true + fecha_creacion: "2026-01-20" + componentes_reutilizables: 3 + paginas: 14 + contexts: 1 + servicios_api: 12 + # ============================================================================ # HERENCIA (Proyecto Independiente) # ============================================================================ @@ -101,9 +112,9 @@ herencia: # ESTADISTICAS VALIDADAS # ============================================================================ estadisticas: - total_definiciones: 7 + total_definiciones: 8 total_referencias_ws: 6 - ultima_actualizacion: "2026-01-17" + ultima_actualizacion: "2026-01-20" validacion: fecha: "2026-01-17" metodo: "Comparacion directa con codigo fuente" diff --git a/orchestration/inventarios/FRONTEND_INVENTORY.yml b/orchestration/inventarios/FRONTEND_INVENTORY.yml index a9af940b7..400304ccb 100644 --- a/orchestration/inventarios/FRONTEND_INVENTORY.yml +++ b/orchestration/inventarios/FRONTEND_INVENTORY.yml @@ -48,10 +48,12 @@ configuracion: resumen: total_paginas: 14 - total_componentes: 50 - total_contexts: 3 - total_servicios_api: 17 + total_componentes_reutilizables: 3 # Layout, ClabeDisplay, CodiQR + total_componentes_internos_paginas: 8 # Modales y subcomponentes en paginas + total_contexts: 1 # AuthContext + total_servicios_api: 12 # Grupos de API en lib/api.ts arquitectura: "SPA" + documentacion: "docs/_definitions/COMPONENTES-FRONTEND.md" paginas_nuevas: - Tokens (Tienda de Tokens - Sprint 6) - CodiSpei (CoDi QR + SPEI CLABE - Sprint 6) @@ -274,15 +276,80 @@ componentes: layout: - nombre: "Layout" archivo: "components/Layout.tsx" - lineas: 168 - descripcion: "Layout principal con sidebar y navegacion" + lineas: 178 + descripcion: "Layout principal con sidebar responsive y navegacion completa" + estado_interno: + - sidebarOpen (boolean) + hooks_usados: + - useState + - useNavigate + - useAuth + dependencias: + - react-router-dom (Outlet, NavLink, useNavigate) + - lucide-react (16 iconos) + - clsx + - AuthContext caracteristicas: - Sidebar fijo (desktop) / colapsable (mobile) - - 7 items de navegacion - - Header mobile con menu - - Bloque de usuario + - 12 items de navegacion + - Header mobile con menu hamburger + - Avatar con iniciales del tenant - Boton de logout - - Outlet para paginas + - Outlet para renderizar paginas + + payments: + - nombre: "ClabeDisplay" + archivo: "components/payments/ClabeDisplay.tsx" + lineas: 113 + descripcion: "Muestra y permite copiar la CLABE virtual para SPEI" + props: + - showCreateButton (boolean, default: true) + - beneficiaryName (string, optional) + estado_interno: + - copied (boolean) + hooks_usados: + - useState + - useQuery + - useMutation + - useQueryClient + dependencias: + - "@tanstack/react-query" + - lucide-react (Copy, Check, Building) + - codiSpeiApi + caracteristicas: + - CLABE formateada (XXX XXX XXXX XXXX XXXX) + - Copiar al clipboard + - Crear CLABE si no existe + - Estados loading/vacio + + - nombre: "CodiQR" + archivo: "components/payments/CodiQR.tsx" + lineas: 168 + descripcion: "Genera y muestra QR de cobro CoDi con temporizador" + props: + - amount (number, requerido) + - description (string, optional) + - saleId (string, optional) + - onSuccess (callback, optional) + - onCancel (callback, optional) + estado_interno: + - transactionId (string | null) + - timeLeft (number, inicia en 300) + hooks_usados: + - useState + - useEffect (x3) + - useMutation + - useQuery + dependencias: + - "@tanstack/react-query" + - lucide-react (QrCode, Clock, Check, X, RefreshCw) + - codiSpeiApi + caracteristicas: + - Genera QR automaticamente + - Countdown 5 minutos + - Polling cada 3s + - Estados (loading, confirmado, expirado) + - Regenerar QR # ============================================================================ # CONTEXTS