Volver al mercado 3D

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

  1. La ficha agrega el producto al carrito del sitio.
  2. El carrito abre con el mismo panel de la tienda y el mismo subtotal.
  3. Finalizar compra lleva al checkout existente, con sus reglas de envío, comprobante y pago.
  4. 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

  1. Definir moneda explícita si se quiere mostrar otra que no sea el precio de la tienda tal cual.
  2. Definir si existirá inventario real; hoy la disponibilidad es ilimitada por producto publicado.
  3. Cargar imágenes y modelos GLB optimizados por producto para los estantes.
  4. Definir el SKU oficial si se necesita conciliar con el ERP o el checkout.
  5. 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.