QMX 3D Market — Mercado con catálogo real
Ruta: /market-3d. Lee el catálogo real de la tienda en modo solo lectura y usa el mismo carrito y el mismo checkout del sitio. No modifica el esquema, los datos ni los permisos de la tienda.
1. Estado
- Escena 3D en primera persona con entrada, pasillo central, cinco stands (Bienestar / Proteína, NOVÜ · Geles, Hidratación, Frutas QMX y Coming Soon), señalización y caja.
- Catálogo conectado a la entidad Product de esta app: mismos nombres, precios, imágenes y categorías que la tienda.
- Los productos marcados como próximamente no se cargan en el mercado.
- Disponibilidad ilimitada mientras el producto esté publicado: la entidad no declara inventario.
- Carrito único: el del sitio. Lo que se agrega en 3D aparece en el carrito de la tienda y viceversa.
- La compra se completa en el checkout existente. El mercado no crea pedidos propios, no descuenta inventario y no procesa pagos por su cuenta.
- Modo 2D accesible con el mismo catálogo y el mismo carrito.
2. Stack real
La escena se construyó directamente sobre Three.js, ya instalado en la app: corre dentro del frontend React, sin iframe ni servicio externo. Migrar a React Three Fiber más adelante no exige cambiar el adaptador de catálogo.
3. Capas
- Página y estado de UI: src/pages/Market3D.jsx
- Escena y geometría: src/components/market/MarketScene.jsx y marketWorld.js
- Controles táctiles: src/components/market/VirtualJoystick.jsx
- Ficha de producto: src/components/market/ProductFocusCard.jsx
- Carrito: carrito compartido del sitio (src/lib/cart-context.jsx) y su panel (src/components/site/CartDrawer.jsx)
- Adaptador de catálogo: src/lib/market/catalogProvider.js
- Prueba de conexión: /market-admin
- Documentación: /market-3d/documentacion
4. Origen de datos
Se lee la entidad Product con un filtro que excluye los productos marcados como próximamente.
Mapeo de campos:
- id original: se conserva como identificador y llave del carrito.
- slug: se usa como SKU legible, porque la entidad no tiene SKU propio.
- name, image_url, price, category, ingredients y supplement_facts: se muestran tal cual.
- serving_size: se presenta como porción.
- coming_soon: define la publicación.
Campos que la fuente no declara y por eso no se inventan: moneda explícita, stock y estado de publicación distinto de próximamente.
Zonas por categoría: protein, performance, amino y preworkout van a Bienestar / Proteína; rehidrante a Hidratación; gel a NOVÜ. El stand Frutas QMX carga el catálogo de frutas de la tienda (precio por unidad) y los productos marcados como próximamente pasan al stand Coming Soon, sin compra.
5. Adaptador
- toShelfItem normaliza cada producto real a la forma que consumen los estantes.
- loadCatalog devuelve productos, aviso y error. Nunca escribe ni crea registros.
- Sin productos publicados, la interfaz muestra un estado vacío; con error de lectura, un mensaje y un botón para reintentar.
6. Compra
- La ficha agrega el producto al carrito del sitio.
- El carrito abre con el mismo panel de la tienda y el mismo subtotal.
- Finalizar compra lleva al checkout existente, con sus reglas de envío, comprobante y pago.
- El mercado no genera pedidos, no descuenta stock y no reimplementa el cobro.
Los productos próximamente no se cargan en el mercado, así que no aparece un botón de compra inactivo.
7. Seguridad y permisos
- Ninguna clave ni token vive en el cliente.
- El catálogo se lee con la sesión de la app, respetando la seguridad por fila configurada en la tienda.
- El panel de conexión exige rol de administrador.
- No se modificaron permisos, esquema ni datos.
- No se envían datos personales a analítica desde el mercado.
8. Variables de entorno
No se requieren. El adaptador lee la misma base de datos de la app y se retiró la dependencia de un endpoint externo.
9. Rendimiento y accesibilidad
- Densidad de píxeles limitada, sin sombras dinámicas y geometría compartida.
- El botón Rendimiento muestra fps, tiempo de carga, draw calls, triángulos y geometrías.
- Se respeta prefers-reduced-motion.
- Modo 2D accesible y activación automática cuando el navegador no ofrece WebGL.
10. Pruebas
- Lectura del catálogo real: verificada; devuelve los productos publicados.
- Exclusión de próximamente: verificada; los productos marcados no aparecen ni se pueden agregar.
- Carrito compartido: lo agregado en 3D se ve en el carrito de la tienda y llega al checkout.
- Apertura de ficha por clic, toque o tecla E: implementado.
- Movimiento con WASD, flechas, joystick y arrastre: implementado.
- Colisiones con estantes y muros: implementado.
- Fallback 2D: manual y automático sin WebGL.
- Panel de conexión: muestra los cinco primeros productos publicados, el conteo y los campos ausentes.
11. Pendientes
- Definir moneda explícita si se quiere mostrar otra que no sea el precio de la tienda tal cual.
- Definir si existirá inventario real; hoy la disponibilidad es ilimitada por producto publicado.
- Cargar imágenes y modelos GLB optimizados por producto para los estantes.
- Definir el SKU oficial si se necesita conciliar con el ERP o el checkout.
- Retirar la función createMarketCheckout y las entidades de demostración cuando ya no se usen; hoy quedan sin uso.
12. Cómo probarlo
Entra a /market-3d, camina con WASD o el joystick, abre una ficha, agrega productos al carrito y pulsa Finalizar compra para completar el flujo en el checkout de la tienda. En /market-admin puedes probar la conexión y ver los primeros productos reales.