paint-brush
Cómo utilizar NextJS, TypeScript, Tailwind y OneEntry CMS para crear una tienda de comercio electrónico 🛒👨‍💻by@madzadev
1,519
1,519

Cómo utilizar NextJS, TypeScript, Tailwind y OneEntry CMS para crear una tienda de comercio electrónico 🛒👨‍💻

Madza2024/01/24
Read on Terminal Reader
Read this story w/o Javascript

Construiremos un proyecto práctico de comercio electrónico para ver cómo NextJS, TypeScript, Tailwind CSS y OneEntry CMS funcionan juntos y cómo podrían usarse para simplificar la administración de contenido.
featured image - Cómo utilizar NextJS, TypeScript, Tailwind y OneEntry CMS para crear una tienda de comercio electrónico 🛒👨‍💻
Madza HackerNoon profile picture
0-item

Introducción

Este es un artículo de asociación patrocinado por OneEntry CMS .


Crear una aplicación de comercio electrónico suele ser una tarea desafiante. Con tantas alternativas disponibles, no es fácil elegir una pila tecnológica que se ajuste a los requisitos del proyecto, las necesidades de escalabilidad y la sostenibilidad a largo plazo.


Otro punto crucial es que los proyectos de comercio electrónico manejan muchos datos y operaciones CRUD. Crear un sistema backend sólido, escalable y seguro puede llevar mucho tiempo incluso para los desarrolladores más experimentados.


Elegí una pila tecnológica basada en NextJS, TypeScript, Tailwind CSS y OneEntry CMS. Nosotros mismos crearemos un proyecto práctico de comercio electrónico para ver cómo funciona en conjunto y cómo podría usarse para simplificar la gestión de contenido.


El código de este proyecto estará disponible en el repositorio de GitHub .

La elección de la pila tecnológica

NextJS es un marco React para crear aplicaciones web rápidas y eficientes, que viene con características como representación de cliente y servidor, recuperación de datos, controladores de ruta, middleware, optimizaciones integradas y mucho más.


TypeScript agrega escritura estática a JavaScript, lo que facilita la detección y corrección de errores en proyectos escalables como el comercio electrónico. También aumenta la productividad a través de funciones como el autocompletado y la asistencia de refactorización.


Tailwind CSS acelera la parte de estilo de las aplicaciones web, lo que permite a los desarrolladores diseñar los elementos dentro del marcado sin la necesidad de cambiar entre archivos CSS externos y crear nombres de clase para cada uno.


OneEntry CMS es un sistema de administración de contenido sin cabeza con una interfaz fácil de usar, backend fácilmente escalable, API rápida y documentación clara para aumentar su productividad en la experiencia de creación y administración de contenido de sitios web.

Contenido y diseño

La página de inicio mostrará el título del encabezado, enumerará las características de la tienda e incluirá la imagen principal.


Página de inicio de la tienda de comercio electrónico


La primera sección de la tienda estará dedicada a la Ropa.


Página de productos de la tienda de comercio electrónico


La segunda sección de la tienda incluirá el Gear.


Página de productos de la tienda de comercio electrónico n.° 2


Cada uno de los elementos tendrá una página de vista previa individual con detalles.


Página de vista previa del producto de la tienda de comercio electrónico


Los artículos que ya estén en el carrito tendrán la opción de eliminarlos.


Página de vista previa del producto de la tienda de comercio electrónico n.° 2


El carrito enumerará todos los artículos seleccionados y calculará el total.


Página del carrito de la tienda de comercio electrónico

Crear proyecto OneEntry

Primero, el usuario deberá registrarse para obtener una nueva cuenta. Para hacerlo, navegue hasta la página de inicio de OneEntry y regístrese a través de su cuenta de correo electrónico.


Página de registro de OneEntry


Después de eso, inicie sesión y será dirigido al panel de OneEntry.


Comience creando un nuevo proyecto.


Página del panel de OneEntry


Recibirás el código gratuito para utilizar el plan de estudios durante un mes. Tendrás la oportunidad de activarlo durante el proceso de creación del proyecto.


Página del proyecto OneEntry


La creación del proyecto tardará unos minutos. Una vez que esté listo, el estado del proyecto cambiará a "Trabajando" y el indicador de estado será verde.


Página del panel de OneEntry

Creando las páginas

Una vez creado el proyecto, recibirá un correo electrónico con los detalles de inicio de sesión para acceder a su portal CMS para crear y almacenar los datos de la aplicación.


Página de inicio de sesión de OneEntry CMS


Después de iniciar sesión, podrá crear su primera página.


Navegue hasta Gestión de contenido, haga clic en Crear una página nueva y complete todos los datos requeridos: tipos de páginas, título de la página, ULR de la página y nombre del elemento del menú.


OneEntry CMS: editar una página


Todos los datos se guardan automáticamente al ingresar.


Crea 4 páginas diferentes para Hogar, Ropa, Equipo y Carro. Una vez creadas, las páginas deberían verse como en la captura de pantalla siguiente.


Lista de páginas de OneEntry CMS

Crear atributos

A continuación, debemos crear la estructura de datos que almacenaremos. En OneEntry CMS, esto se logra creando los atributos para los datos.


Navegue a Configuración y elija Atributos en el menú horizontal. Cree un conjunto de atributos para la página de inicio que proporcione el nombre, el marcador y el tipo:


Tipos de páginas de OneEntry CMS


Una vez creado, se verá como en la siguiente captura de pantalla:


Atributos de la página OneEntry CMS


De manera similar, creemos dos conjuntos de atributos separados para Ropa y Equipo. Una vez creado, el resultado debería verse como en la captura de pantalla siguiente.


Atributos de OneEntry CMS n.º 2


Ahora, definamos atributos específicos para cada conjunto.


Según el contenido que incluimos anteriormente en la estructura alámbrica de la sección Inicio, queremos mostrar el título, la descripción y la imagen.


Haga clic en el elemento de engranaje de Inicio y cree los siguientes nombres de atributos, marcadores y tipos de atributos como se muestra en la lista a continuación.


Configuración de la página OneEntry CMS


Ahora, regresa y haz clic en el ícono de ajustes de Ropa.


Los atributos de esta página serán un poco diferentes ya que queremos mostrar el título, subtítulo, descripción, imagen y precio del producto.


Así es como se vería la estructura de atributos:


Atributos de la página OneEntry CMS


A continuación, haga lo mismo con la página Gear, que utilizará la misma estructura:


Atributos de la página OneEntry CMS n.° 2

Agregar contenido

En esta etapa del proyecto, ya hemos definido la estructura del contenido y estamos listos para comenzar a crear el contenido en sí.


Navegue a la sección Gestión de contenido donde previamente creó todas sus páginas para el sitio:


Lista de páginas de OneEntry CMS


Haga clic en el botón editar de Inicio. Después de eso, haga clic en la pestaña Atributos en el menú Horizontal:


Atributos de selección de OneEntry CMS


Seleccione Inicio para el Conjunto de atributos. Eso cargará todos los atributos que creamos previamente en Configuración para la página de inicio.


Ahora complete algunos datos de muestra que desea que se muestren en la página de inicio.


Creación de contenido OneEntry CMS


Ahora, agreguemos algo de contenido para nuestras páginas de Ropa y Equipo.


Dado que seleccionamos el tipo de página como Catálogo, seleccione Catálogo en el menú de la izquierda y ambas páginas deberían estar visibles allí:


Catálogo OneEntry CMS


Ahora, haga clic en el ícono Agregar de Ropa y agregue algunos artículos.


Primero, agregue el encabezado del producto que desea agregar.


Encabezado del catálogo de OneEntry CMS


Ahora cambie a la pestaña Atributos, seleccione Ropa para el Conjunto de atributos y complete los datos requeridos.


OneEntry CMS agregar productos


Regrese al menú Catálogo y a algunos elementos más tanto para Ropa como para Equipo. Para nuestra aplicación de demostración, agregué 4 elementos como se muestra en la siguiente captura de pantalla:


Listas de productos OneEntry CMS

Crear un token de acceso API

Todos los datos creados en el CMS OneEntry están protegidos, por lo que tendremos que crear un token privado para poder acceder a ellos.


Para hacerlo, navegue hasta Configuración y seleccione Tokens de aplicación. Ingrese el nombre de la aplicación y la fecha de vencimiento y haga clic en Crear. Esto generará una clave API única.


OneEntry CMS: crear token de aplicación


Haga clic en el icono de vista en la lista de acciones y podrá ver la clave. Cópielo al portapapeles ya que lo necesitaremos en la siguiente sección del tutorial.


OneEntry CMS: copiar token de aplicación

Configurando el proyecto NextJS

En esta sección del tutorial, comenzaremos a trabajar con el código y configuraremos el proyecto NextJS para que funcione con OneEntry CMS.


Abra la terminal y ejecute el comando npx create-next-app@latest .


La CLI iniciará el asistente de configuración. Ingrese el nombre de su proyecto y seleccione todos los valores predeterminados como se muestra a continuación:


Asistente de configuración de NextJS en la terminal


Espere un minuto a que se complete la configuración y recibirá una notificación cuando se haya creado la aplicación NextJS.


Después de eso, cambie el directorio a la carpeta recién creada usando el comando cd winter-sports y luego ejecute npm run dev para iniciar el servidor de desarrollador.


Para acceder a él, haga clic en el enlace proporcionado en el terminal o abra su navegador web y navegue hasta http://localhost:3000 manualmente.


Debería aparecer la página de inicio del servidor para desarrolladores NextJS:


Vista previa del servidor de desarrollador NextJS


Ahora, creemos un valor ambiental que necesitaremos para nuestra aplicación. Vuelva a su editor de código y cree un archivo .env en la raíz de su proyecto.


Pegue la clave API que copió en el portapapeles anteriormente de la siguiente manera:


 API_KEY=your-api-code-from-oneentry


Esto nos permitirá acceder a la clave a través de process.env.API_KEY una vez que realicemos las llamadas a la API para recuperar los datos del OneEntry CMS.


También necesitamos configurar NextJS, para que nos permita incluir los medios de un dominio externo. Lo necesitaremos para acceder a las imágenes desde OneEntry CMS.


Abra el archivo next.config.js en la raíz del proyecto y edítelo de la siguiente manera:


 const nextConfig = { images: { remotePatterns: [ { hostname: "ecommerce.oneentry.cloud", }, ], }, }; module.exports = nextConfig;


Finalmente, necesitaremos restablecer el estilo predeterminado de Tailwind para la aplicación, ya que escribiremos todos los estilos desde cero.


Abra el archivo globals.css en el directorio app que se encuentra en la carpeta src y cambie el contenido del archivo a lo siguiente:


 @tailwind base; @tailwind components; @tailwind utilities;

Crear tipos

Dado que trabajaremos con TypeScript, necesitaremos definir qué tipos de datos usaremos en nuestra aplicación.


Podríamos hacer esto dentro de las páginas y componentes, pero para mantener el código más limpio y evitar repeticiones, cree una nueva carpeta interfaces dentro del directorio de la app . Cree un archivo data.tsx dentro de la carpeta recién creada e incluya el código:


 export interface Product { id: string; category: string; title: string; subtitle: string; description: string; image: string; price: number; } export interface ProductAPI { id: string; attributeValues: { en_US: { producttitle: { value: { htmlValue: string }[]; }; productsubtitle: { value: { htmlValue: string }[]; }; productdescription: { value: { htmlValue: string }[]; }; productimage: { value: { downloadLink: string }[]; }; productprice: { value: number; }; }; }; } export interface Page { pageUrl: string; title: string; description: string; image: string; localizeInfos: { en_US: { title: string; }; }; } export interface PageAPI { attributeValues: { en_US: { herotitle: { value: { htmlValue: string }[]; }; herodescription: { value: { htmlValue: string }[]; }; heroimage: { value: { downloadLink: string }[]; }; }; }; } export interface URLProps { params: { category: string; productId: string; }; } export interface TextProps { className: string; text: string; }


Los datos de productos y páginas tendrán tipos para su estructura de datos de representación de front-end y la respuesta de la API a través del método de recuperación.


Además, definimos los tipos de datos para los datos de los parámetros de URL y el procesador de texto para los datos recibidos de los campos de entrada de texto en CMS.

Crear funciones de recuperación de API

Ahora, creemos algunas funciones que usaremos para comunicarnos con OneEntry CMS para recuperar los datos de las páginas y productos.


Nuevamente, podríamos hacer esto en cada archivo, pero para mantener el código más limpio, creemos una nueva carpeta de services dentro del directorio de la app con un archivo fetchData.tsx dentro:


 export async function getPages() { const response = await fetch( "https://ecommerce.oneentry.cloud/api/content/pages", { method: "GET", headers: { "x-app-token": `${process.env.API_KEY}`, }, } ); return await response.json(); } export async function getProducts(category: string) { const response = await fetch( `https://ecommerce.oneentry.cloud/api/content/products/page/url/${category}?limit=4&offset=0&langCode=en_US&sortOrder=DESC&sortKey=id`, { method: "GET", headers: { "x-app-token": `${process.env.API_KEY}`, }, } ); return await response.json(); } export async function getProduct(id: string) { const response = await fetch( `https://ecommerce.oneentry.cloud/api/content/products/${id}`, { method: "GET", headers: { "x-app-token": `${process.env.API_KEY}`, }, } ); return await response.json(); }


La función getPages recuperará los datos sobre todas las páginas que creamos en OneEntry CMS.


La función getProducts obtendrá los datos de una colección específica de productos según el parámetro category . Pasaremos el parámetro cuando importemos la función a la página de productos.


La función getProduct obtendrá los datos según la id del producto que abrimos. Pasaremos el parámetro cuando importemos la función a la página de vista previa de cualquier producto específico.


Tenga en cuenta que utilizamos process.env.API_KEY para acceder a la clave API que definimos en el archivo .env anteriormente para autenticar el acceso a OneEntry CMS.

Crear funciones auxiliares

Además, mientras todavía estamos en la carpeta services , creemos otro archivo nuevo dentro de ella llamado helpers.tsx que incluirá pequeñas funciones de utilidad:


 export function calculateTotal(items: { price: number }[]) { return items.reduce((total, item) => total + Number(item.price), 0); } export function boughtStatus(items: { id: string }[], id: string) { return items.some((item) => item.id === id); } export function cartIndex(items: { id: string }[], id: string) { return items.findIndex((item) => item.id === id); }


La función calculateTotal sumará los precios de los productos agregados al carrito y devolverá el valor total.


El boughtStatus detectará si los artículos individuales en la ruta de vista previa ya se han agregado al carrito.


cartIndex detectará la posición del artículo en la matriz de los productos que se han agregado al carrito.

Creando componentes

Vuelva al directorio app y cree una nueva carpeta de components dentro de él.


Abra la carpeta recién creada e incluya siete archivos separados en ella: Header.tsx , Footer.tsx , Text.tsx , Card.tsx , Preview.tsx , Order.tsx , AddToCart.tsx .


Componente de encabezado

Abra el archivo Header.tsx e incluya el siguiente código:


 import Link from "next/link"; import { Page } from "../interfaces/data"; export default function Header({ pages }: { pages: Page[] }) { return ( <div className="flex justify-between items-center mb-10 p-6"> <Link href="/"> <h1 className="text-xl">🏂 Alpine Sports</h1> </Link> <div className="flex space-x-4 list-none"> {pages.map((page, index: number) => ( <Link key={index} href={page.pageUrl === "home" ? "/" : `/${page.pageUrl}`} > {page.localizeInfos.en_US.title} </Link> ))} </div> </div> ); }

Para el encabezado, mostramos el nombre de la empresa y recorrimos los enlaces de navegación que obtendremos de la API una vez que el componente se importe a las páginas.


Creamos un diseño de dos columnas y colocamos ambos elementos en lados opuestos de la pantalla horizontalmente para lograr el aspecto de navegación típico.


Componente de pie de página

Abra el archivo Footer.tsx e incluya el siguiente código:


 export default function Footer() { return ( <div className="text-center mt-auto p-6"> <h1>Alpine Sports, Inc.</h1> <p>All rights reserved, {new Date().getFullYear()}</p> </div> ); }


En el pie de página, incluimos el nombre de muestra de la empresa y los derechos del contenido con el año actual. Centramos el contenido y agregamos algo de relleno.


Componente de texto

Abra el archivo Text.tsx e incluya el siguiente código:


 import { TextProps } from "../interfaces/data"; export default function Text({ className, text }: TextProps) { return ( <div className={className} dangerouslySetInnerHTML={{ __html: text }} /> ); }


El componente Texto representará los datos de texto que recibimos del OneEntry CMS y los mostrará correctamente en nuestra aplicación sin etiquetas HTML.


Componente de la tarjeta

Abra el archivo Card.tsx e incluya el siguiente código:


 import Link from "next/link"; import Text from "../components/Text"; import { Product } from "../interfaces/data"; export default function Card({ product }: { product: Product }) { return ( <Link href={`/${product.category}/${product.id}`}> <div className="group relative"> <div className="group-hover:opacity-75 h-80"> <img src={product.image} alt="Product card image" className="h-full w-full object-cover object-center" /> </div> <div className="mt-4 flex justify-between"> <div> <h3 className="text-sm text-gray-700"> <Text className="" text={product.title} /> </h3> <Text className="mt-1 text-sm text-gray-500" text={product.subtitle} /> </div> <p className="text-sm font-medium text-gray-900">${product.price}</p> </div> </div> </Link> ); }


En el componente de tarjeta, mostramos la imagen, título, subtítulo y precio de cada producto. Mapearemos todos los elementos una vez que se importen a las páginas.


La imagen se mostrará en la parte superior de la tarjeta, seguida del título y la descripción, y el precio en la parte inferior derecha del componente.


Componente de vista previa

Abra el archivo Preview.tsx e incluya el siguiente código:


 "use-client"; import Image from "next/image"; import Text from "./Text"; import { Product } from "../interfaces/data"; export default function Preview({ children, productItem, }: { children: React.ReactNode; productItem: Product; }) { return ( <div className="flex mx-auto max-w-screen-xl"> <div className="flex-1 flex justify-start items-center"> <Image src={productItem.image} alt="Product preview image" width="450" height="900" /> </div> <div className="flex-1"> <Text className="text-5xl pb-8" text={productItem.title} /> <Text className="text-4xl pb-8 text-gray-700" text={`$${productItem.price}`} /> <Text className="pb-8 text-gray-500 text-justify" text={productItem.description} /> {children} </div> </div> ); }


El componente de vista previa se utilizará para mostrar más información sobre cada producto una vez que el usuario haga clic en él.


Mostraremos la imagen del producto, el título, el precio y la descripción. El diseño se dividirá en 2 columnas, donde la imagen se mostrará en la columna de la izquierda y el resto del contenido en la derecha.


Componente de pedido

Abra el archivo Order.tsx e incluya el siguiente código:


 "use client"; import { useState, useEffect } from "react"; import Link from "next/link"; import Image from "next/image"; import Text from "./Text"; import { calculateTotal } from "../services/helpers"; import { Product } from "../interfaces/data"; export default function Order() { const [cartItems, setCartItems] = useState<Product[]>([]); useEffect(() => { const storedCartItems = localStorage.getItem("cartItems"); const cartItems = storedCartItems ? JSON.parse(storedCartItems) : []; setCartItems(cartItems); }, []); return ( <div> {cartItems.map((item, index) => ( <div key={index} className="flex items-center border-b border-gray-300 py-2" > <div className="w-20 h-20 mr-12"> <Image src={item.image} alt={item.title} width={80} height={80} /> </div> <div> <Link href={`/${item.category}/${item.id}`} className="text-lg font-semibold" > <Text className="" text={item.title} /> </Link> <Text className="text-gray-600" text={item.subtitle} /> <p className="text-gray-800">Price: ${item.price}</p> </div> </div> ))} <div className="mt-4 text-end"> <h2 className="text-xl font-semibold mb-8"> Total Amount: ${calculateTotal(cartItems)} </h2> <button className="bg-blue-500 hover:bg-blue-700 py-2 px-8 rounded"> Proceed to checkout </button> </div> </div> ); }


El componente del pedido enumerará todos los artículos que el usuario ha agregado al carrito. Para cada artículo, se mostrará la imagen, título, subtítulo y precio.


Una vez que se represente el componente, la aplicación accederá a todos los artículos actualmente en el carrito, los configurará en la variable de estado cardItems y los mostrará en la pantalla mediante el método map .


La cantidad total de los elementos renderizados se calculará mediante la función calculateTotal , que importamos del archivo helpers.tsx .


Componente AddToCart

Abra el archivo AddToCart.tsx e incluya el siguiente código:


 "use client"; import React, { useState, useEffect } from "react"; import { boughtStatus, cartIndex } from "../services/helpers"; import { Product } from "../interfaces/data"; export default function AddToCart({ category, id, title, subtitle, image, price, }: Product) { const storedCartItems = JSON.parse(localStorage.getItem("cartItems") || "[]"); const isPurchased = boughtStatus(storedCartItems, id); const indexInCart = cartIndex(storedCartItems, id); const [btnState, setBtnState] = useState(false); useEffect(() => { isPurchased && setBtnState(true); }, []); const handleButtonClick = () => { const updatedCartItems = [...storedCartItems]; if (!btnState && !isPurchased) { updatedCartItems.push({ category, id, title, subtitle, image, price }); } else if (isPurchased) { updatedCartItems.splice(indexInCart, 1); } localStorage.setItem("cartItems", JSON.stringify(updatedCartItems)); setBtnState(!btnState); }; return ( <button className={`${ !btnState ? "bg-blue-500 hover:bg-blue-600" : "bg-yellow-300 hover:bg-yellow-400" } py-2 px-8 rounded`} onClick={handleButtonClick} > {!btnState ? "Add to Cart" : "Remove from Cart"} </button> ); }


El componente addToCart se mostrará en la página de vista previa del producto individual y permitirá al usuario agregar el producto al carrito de compras.


Tras la representación, la función isPurchased detectará si el producto ya se ha agregado al carrito anteriormente. Si no es el botón renderizado, se mostrará "Agregar al carrito"; de lo contrario, dirá "Eliminar del carrito".


La función de clic de la función handleButtonClick agregará o eliminará el producto de la matriz de elementos según el estado anterior.

Crear páginas

Finalmente, importemos los componentes que creamos en la sección anterior del tutorial y creemos la lógica de página para la aplicación.


pagina de inicio

Abra page.tsx en el directorio app y edite su contenido de la siguiente manera:


 import Image from "next/image"; import Header from "./components/Header"; import Text from "./components/Text"; import Footer from "./components/Footer"; import { getPages } from "./services/fetchData"; import { PageAPI } from "./interfaces/data"; export default async function Home() { const pages = await getPages(); const getValues = (el: PageAPI) => { const { herotitle, herodescription, heroimage } = el.attributeValues.en_US; return { title: herotitle.value[0].htmlValue, description: herodescription.value[0].htmlValue, image: heroimage.value[0].downloadLink, }; }; const pageContent = getValues(pages[0]); return ( <div className="flex flex-col min-h-screen"> <Header pages={pages} /> <div className="flex flex-row mx-auto max-w-screen-xl"> <div className="flex-1"> <Text className="text-6xl pb-10 text-gray-900" text={pageContent.title} /> <Text className="text-xl pb-8 text-gray-500 text-justify" text={pageContent.description} /> </div> <div className="flex-1 flex justify-end items-center"> <Image src={pageContent.image} alt="Photo by Karsten Winegeart on Unsplash" width={450} height={900} /> </div> </div> <Footer /> </div> ); }


En la página de inicio, primero llamaremos a la función getPages para obtener los datos del encabezado.


Luego usamos la función getValues para recuperar los datos de la página Hero y luego los convertimos en un objeto pageContent para facilitar el procesamiento.


Luego renderizamos los componentes de encabezado y pie de página importados y pasamos los valores necesarios para el título, la descripción y la imagen del héroe.


Página de productos

Cree una nueva carpeta [category] en el directorio app y dentro de ella, un archivo page.tsx .


El uso de nombres de archivos específicos es importante ya que eso es lo que utiliza NextJS para manejar rutas y acceder a los parámetros de URL.


Incluya el siguiente código en page.tsx :


 import Header from "../components/Header"; import Footer from "../components/Footer"; import Card from "../components/Card"; import { getPages, getProducts } from "../services/fetchData"; import { ProductAPI, URLProps } from "../interfaces/data"; export default async function Product({ params }: URLProps) { const { category } = params; const pages = await getPages(); const products = await getProducts(category); const getValues = (products: ProductAPI[]) => { return products.map((el) => { const { producttitle, productsubtitle, productdescription, productimage, productprice, } = el.attributeValues.en_US; return { id: el.id, category: category, title: producttitle.value[0].htmlValue, subtitle: productsubtitle.value[0].htmlValue, description: productdescription.value[0].htmlValue, image: productimage.value[0].downloadLink, price: productprice.value, }; }); }; const productItems = getValues(products.items); return ( <div className="flex flex-col min-h-screen"> <Header pages={pages} /> <div className="mx-auto max-w-screen-xl px-8"> <h2 className="text-4xl text-gray-900 mb-12"> Browse our {category} collection: </h2> <div className="grid gap-x-6 gap-y-10 grid-cols-4 mt-6"> {productItems.map((product) => { return <Card key={product.id} product={product} />; })} </div> </div> <Footer /> </div> ); }


Para la página de productos, primero obtenemos el parámetro category de la URL, que luego pasamos a la función getProducts , para describir qué categoría de productos necesitamos recuperar en función de la página del sitio que se visita.


Una vez recibidos los datos, creamos una matriz de objetos productItems que consta de todos los atributos necesarios para la página para facilitar su procesamiento.


Luego lo recorremos mediante el método del map y lo representamos en la pantalla pasando accesorios al componente Tarjeta que importamos desde la carpeta del component .


Vista previa de la pàgina

Dentro de la carpeta [category] , cree otra carpeta llamada [productId] .


Abra la carpeta recién creada y cree un archivo page.tsx dentro de ella con el código:


 import Header from "../../components/Header"; import Preview from "../../components/Preview"; import AddToCart from "../../components/AddToCart"; import Footer from "../../components/Footer"; import { getPages, getProduct } from "../../services/fetchData"; import { ProductAPI, URLProps } from "../../interfaces/data"; export default async function Product({ params }: URLProps) { const { category, productId } = params; const pages = await getPages(); const product = await getProduct(productId); const getValues = (el: ProductAPI) => { const { producttitle, productsubtitle, productdescription, productimage, productprice, } = el.attributeValues.en_US; return { id: el.id, category: category, title: producttitle.value[0].htmlValue, subtitle: productsubtitle.value[0].htmlValue, description: productdescription.value[0].htmlValue, image: productimage.value[0].downloadLink, price: productprice.value, }; }; const productItem = getValues(product); return ( <div className="flex flex-col min-h-screen"> <Header pages={pages} /> <div className="flex mx-auto max-w-screen-xl"> <div className="flex-1 flex justify-start items-center"> <Preview productItem={productItem}> <AddToCart id={productId} category={category} title={productItem.title} subtitle={productItem.subtitle} description={productItem.description} image={productItem.image} price={productItem.price} /> </Preview> </div> </div> <Footer /> </div> ); }


Esta página permitirá a los usuarios ver más detalles de cualquier producto individual una vez que hagan clic en sus tarjetas en la página de productos.


Primero obtenemos el parámetro productId de la URL, que luego pasamos a la función getProduct , para especificar qué producto necesitamos recuperar en función del producto que se ve en la página de vista previa.


Una vez recibidos los datos, creamos un objeto productItem que consta de todos los atributos necesarios para pasarlos al componente Vista previa como accesorios.


También obtenemos el parámetro category , ya que debemos pasarlo al componente Agregar al carrito, para que podamos crear un enlace válido para el artículo en la página del carrito.


Página del carrito

Finalmente, cree un nuevo cart de carpetas en el directorio app .


Ábralo, cree un nuevo archivo page.tsx dentro de él con el siguiente código:


 import Header from "../components/Header"; import Order from "../components/Order"; import Footer from "../components/Footer"; import { getPages } from "../services/fetchData"; export default async function Cart() { const pages = await getPages(); return ( <div className="flex flex-col min-h-screen"> <Header pages={pages} /> <div className="container mx-auto max-w-screen-xl px-8"> <h2 className="text-4xl text-gray-900 mb-12">Shopping cart summary:</h2> <Order /> </div> <Footer /> </div> ); }


Primero obtuvimos los datos necesarios y luego los pasamos al encabezado como accesorios.


Luego representamos el componente de encabezado con la navegación, el componente de pedido que enumerará todos los artículos que el usuario agregó al carrito y también el componente de pie de página con el nombre de la empresa y la información de derechos de autor.

Pruebas

¡Felicitaciones, ha realizado un proyecto que funciona!


Primero, verifique si el servidor de desarrollador todavía se está ejecutando. Si no es así, ejecute el comando npm run dev para iniciarlo nuevamente y acceda a localhost:3000 para verlo.


Su proyecto ahora debería verse así:


Tutorial final del proyecto


Como puede ver, el contenido de la sección Inicio se obtuvo correctamente del conjunto de atributos de Inicio que especificamos en los campos de datos.


Además, todos los artículos del catálogo de OneEntry CMS se han obtenido en las secciones Ropa y Equipo con toda la información correctamente representada.


Los usuarios también pueden obtener una vista previa de cada producto por separado en su página dedicada, gracias al manejo de rutas y los parámetros del producto de NextJS.


Además, todas las funciones y eventos funcionan como se esperaba, y el usuario puede agregar y quitar artículos del carrito de compras, calculándose el total.

Conclusión

En este tutorial, creamos un proyecto de comercio electrónico que permite a los usuarios crear, actualizar y eliminar páginas de sitios web y su contenido, así como administrar fácilmente productos con una interfaz de catálogo fácil de usar, gracias a OneEntry CMS .


El código está disponible en GitHub , así que siéntete libre de clonarlo y agregarle más funciones para satisfacer tus necesidades. Puede agregarle más secciones de menú, ampliar componentes individuales o incluso agregar más componentes para implementar nuevas funciones.


Con suerte, esto le resultará útil y obtendrá una idea de cómo utilizar OneEntry CMS como solución backend, cómo combinarlo con el front-end de su aplicación y cómo utilizar las mejores funciones de NextJS, Typecript y Tailwind. .


¡Asegúrese de recibir los mejores recursos, herramientas, consejos de productividad y consejos de crecimiento profesional que descubro al suscribirme a mi boletín !


Además, conéctate conmigo en Twitter , LinkedIn y GitHub .


También publicado aquí