En esta publicación queremos descubrir el uso de un front-end propulsado por Gatsby con HCL Commerce, como plataforma de headless commerce. El objetivo principal es sustituir las funciones básicas de la tienda Aurora starter con la tienda de tecnología Gatsby. La tienda debería tener una página de inicio (HP), una página de lista de productos (PLP), una página de detalle del producto (PDP) y un checkout. La intención de la publicación es dar una idea general de cómo se puede lograr este objectivo, junto con unos ejemplos de código.

 

Configuración

Para configurar el entorno de desarrollo, seguimos los siguientes pasos:
  • Instalar Node.js: Descarga e instala la última versión de Node.js desde el sitio web oficial de Node.js
  • Instalar Git
  • Instalar Gatsby CLI: La CLI de Gatsby está disponible a través de npm y debe instalarse globalmente, ejecutando npm install -g gatsby-cli
  • Crear un sitio Gatsby: gatsby new gatsby https://github.com/gatsbyjs/gatsby-starter-hello-world

Después, hacemos cd gatsbygatsby develop para iniciar el servidor de desarrollo Gatsby. Podemos acceder al sitio starter de Gatsby en http://localhost:8000/. Para obtener más información y tutoriales sobre Gatsby, consulta Gatsby docs.

Extracción de datos y generación de páginas

Gatsby puede extraer datos de Headless CMS, bases de datos, API y más. Existen tres métodos que podemos aplicar para obtener datos de nuestra API privada:
  1. Si la API privada es API GraphQL, usamos gatsby-source-graphql.
  2. Si la API privada no es una API GraphQL y eres nuevo en GraphQL, trata los datos como datos no estructurados y recójelos durante el tiempo de compilación, como se describe en la guía ”Using Gatsby without GraphQL”. Sin embargo, como se destaca en la guía, este método viene con algunos compromisos.
  3. Crear un source plugin, como se describe en el tutorial ”Source plugin tutorial

Explicaremos cómo podemos usar la opción dos para obtener los datos que necesitamos de las API de HCL Commerce y crear páginas de la tienda. El archivo gatsby-node.js se usa para obtener los datos y crear los PDP y PLP:

/**
 * Implement Gatsby's Node APIs in this file.
 *
 * See: https://www.gatsbyjs.org/docs/node-apis/
 */

// You can delete this file if you're not using it
const axios = require('axios');

const get = endpoint => axios.get(`http://localhost:80/wcs/resources/store/1/productview/byCategory/10001`);

const getProductData = categoryIds =>
Promise.all(
    categoryIds.map(async id => {
        const { data: CatalogEntryView } = await get(``);
        return { ...CatalogEntryView };
    })
);

exports.createPages = async ({ actions: { createPage } }) => {
    // `getProductData` is a function that fetches our data
    const allCategory = await getProductData(["10001"]);
  
    // Create a page that lists all Product.
    allCategory.forEach(category => {
        createPage({
        path: `/category/10001`,
        component: require.resolve("./src/templates/category.js"),
        context: { category },
        })
    })
  
    // Create a page for each product.
    allCategory.forEach(category => {
        category.CatalogEntryView.forEach(product => {
            createPage({
                path: `/category/10001/product/${product.uniqueID}/`,
                component: require.resolve("./src/templates/product.js"),
                context: { product },
            })
        })
    })
  }

 

Las siguientes plantillas de PLP and PDP se encuentran en src\templates\
import React from 'react';
import { Link } from 'gatsby';

export default ({ pageContext: { category } }) => (
  <div style={{ width: 960, margin: '4rem auto' }}>
    <h1>Product List Page - PLP</h1>
    <h1>Total Products : {category.recordSetCount}</h1>
    <ul style={{ padding: 0 }}>
      {category.CatalogEntryView.map(product => (
        <li
          key={product.uniqueID}
          style={{
            textAlign: 'center',
            listStyle: 'none',
            display: 'inline-block'
          }}
        >
          <Link to={`/category/10001/product/${product.uniqueID}`}>
            <img src={`https://localhost:8443${product.thumbnail}`} alt={product.partNumber} />
            <p>{product.partNumber}</p>
          </Link>
        </li>
      ))}
    </ul>
  </div>
);
import React from 'react';
import { Link } from 'gatsby';

export default ({ pageContext: { product } }) => (
    <div style={{ width: 960, margin: "4rem auto" }}>
      <h1>{product.uniqueID}</h1>
      <h1>{product.name}</h1>
        <h5>{product.shortDescription}</h5>
        <h3>${product.Price[0].priceValue}</h3>
      <h1>{product.partNumber}</h1>
      <img src={`https://localhost:8443${product.thumbnail}`} alt={product.name} />
    </div>
  )

Ahora, después de compilar el código, podemos ver todas las páginas que se crean en public\page-data

  • public\page-data\category\page-data.json
  • public\page-data\category\10001\page-data.json
  • public\page-data\category\10001\product\10039\page-data.json

También sería posible obtener los datos mediante la creación de un source plug-in y luego utilizar GraphQL para hacer referencia a ello en gatsby-node.js. Aqui hay más información sobre source plug-ins de Gatsby. En resumen, un plug-in hace lo siguente:

  • Aceptar opciones de configuración como una clave API y / o un search query
  • Realizar una petición a la API REST de HCL Commerce, utilizando las opciones de configuración proporcionadas
  • Convierte los datos en la respuesta API al sistema de nodos de Gatsby

 

El carrito de compra

Los PDP y PLP fueron páginas generadas que utilizaron fuentes de datos y archivos de plantilla para preparar el HTML final. Para el carrito de compra, preparamos una sola página, y lo hacemos agregando un archivo src/pages/cart.js, así que no se aplican plantillas esta vez. Llamaremos al endpoint de HCL Commerce que proporciona detalles sobre el carrito de compras: http://localhost:80/wcs/resources/store/1/cart/@self?pageSize=50&pageNumber=1&responseFormat=json'. Esto nos proporciona un JSON que contiene todo lo que está en el carrito. Recorremos la respuesta para crear el carrito de compras:

import React, { useState, useEffect } from "react"
import { Link } from "gatsby"

import Layout from "../components/layout"
import SEO from "../components/seo"

const axios = require('axios');
const fetch = require(`node-fetch`);

const CartPage = () => {
  const cartURL = 'http://localhost:80/wcs/resources/store/1/cart/@self?pageSize=50&pageNumber=1&responseFormat=json';

  // Client-side Runtime Data Fetching
  const [cartData, setCartData] = useState(0)
  useEffect(() => {
    // get data from GitHub api
    fetch(cartURL, {credentials: "include"})
      .then(response => response.json()) // parse JSON from request
      .then(resultData => {
        setCartData(resultData)
      })
  }, [])
  return (
    <Layout>
      <SEO title="Shoping Cart" />
      <h1>Shopping cart</h1>
      <table>
        <tr>
          <th>Product</th>
          <th>QTY</th>
          <th>Each</th>
          <th>Total</th>
        </tr>
        {cartData.orderItem && cartData.orderItem.map(item => (
          <tr>
            <td><Link to={`/category/10001/product/${item.productId}`}>{item.partNumber}</Link></td>
            <td>{item.quantity}</td>
            <td>{item.unitPrice}</td>
            <td>{item.orderItemPrice}</td>
          </tr>
        ))}
        <tr>
          <td></td>
          <td></td>
          <td>Order Subtotal:</td>
          <td>{cartData.totalProductPrice}</td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td>Discount:</td>
          <td>({cartData.totalAdjustment})</td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td>Order Total:</td>
          <td>{cartData.grandTotal}</td>
        </tr>
      </table>
    </Layout>
  )
}

export default CartPage;

El carrito de compra Gatsby

<br>Además de tener un carrito de compras, necesitamos una forma de agregar artículos al carrito. Para realizar este objetivo, necesitamos agregar algunas funcionalidades a los PDP. Usamos GET /wcs/resources/store/10001/productview/byId/13011 endpoint para obtener detalles del producto. Luego para agregar al carrito, usamos algo como:

POST /wcs/resources/store/10001/cart?responseFormat=json
{
	"orderId": ".",
	"orderItem": [
		{
			"productId": "10706",
			"quantity": "1"
		}
	],
	"x_calculateOrder": "0",
	"x_inventoryValidation": "true"
}

 

Después de agregar esta lógica adicional al PDP, nos terminará con algo como lo siguiente:

Gatsby PDP

 

Checkout

También necesitamos crear un flujo de pago/checkout para la tienda. Eso implica tres áreas: página de envío / facturación, página de pago / revisión y página de confirmación. Hacemos eso de manera similar a la página del carrito de compras; es decir, agregamos una nueva entrada a src/pages para cada página. Además tendremos que llamar a los endpoints de HCL Commerce adecuados para enviar y recibir datos. Las páginas resultantes se ven así:

Envío y Facturación

Pago y Revisión

Confirmación

 

Espots y contenido de CMC

Si necesitamos mostrar Espots u otro contenido del CMC, se puede acceder fácilmente a través de la API REST de HCL Commerce. La siguiente tabla resume algunos de los endpoints disponibles:

HTTP Method

Path

Descripción

GET

/store/{storeId}/espot?q={q}

Recuperar una lista de todos los términos de búsqueda que tienen reglas de búsqueda.

GET

/store/{storeId}/espot/{name}

Recuperar un e-Marketing Spot por nombre.

GET

/store/{storeId}/espot/{name}/category/{categoryId}

Deprecated: Recuperar un e-Marketing Spot en un nivel de categoría específico. Por ejemplo, muebles. Alternativamente, esto se puede implementar usando el método de findByName, con el siguente URL: store/{storeId}/espot/{name}?categoryId=&DM_ReqCmd=CategoryDisplay.

GET

/store/{storeId}/espot/{name}/product/{productId}

Deprecated: Recuperar un e-Marketing Spot para un producto especifíco. Alternativamente, esto se puede implementar usando el método de findByName, con el siguente URL: store/{storeId}/espot/{name}?productId=&DM_ReqCmd=ProductDisplay.

GET

/store/{storeId}/espot/{name}/type/{type}

Recuperar datos de e-Marketing Spot

 

Conclusión

Hemos creado un front-end funcional para HCL Commerce, utilizando el marco Gatsby. La tienda tiene todas las funcionalidades básicas necesarias para realizar un pago, como agregar al carrito y un flujo de checkout. El usuario puede navegar por todo el catálogo y seleccionar distintas versiones de los productos para agregar a su carrito.