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 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. NextJS es 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. TypeScript 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. Tailwind CSS 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. OneEntry CMS 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. La primera sección de la tienda estará dedicada a la Ropa. La segunda sección de la tienda incluirá el Gear. Cada uno de los elementos tendrá una página de vista previa individual con detalles. Los artículos que ya estén en el carrito tendrán la opción de eliminarlos. El carrito enumerará todos los artículos seleccionados y calculará el total. 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 a través de su cuenta de correo electrónico. regístrese Después de eso, y será dirigido al panel de OneEntry. inicie sesión Comience creando un nuevo proyecto. 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. 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. 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. 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ú. 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. 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: Una vez creado, se verá como en la siguiente captura de pantalla: 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. 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. 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: A continuación, haga lo mismo con la página Gear, que utilizará la misma estructura: 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: Haga clic en el botón editar de Inicio. Después de eso, haga clic en la pestaña Atributos en el menú Horizontal: 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. 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í: Ahora, haga clic en el ícono Agregar de Ropa y agregue algunos artículos. Primero, agregue el encabezado del producto que desea agregar. Ahora cambie a la pestaña Atributos, seleccione Ropa para el Conjunto de atributos y complete los datos requeridos. 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: 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. 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. 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: 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 y luego ejecute para iniciar el servidor de desarrollador. cd winter-sports npm run dev Para acceder a él, haga clic en el enlace proporcionado en el terminal o abra su navegador web y navegue hasta manualmente. http://localhost:3000 Debería aparecer la página de inicio del servidor para desarrolladores NextJS: Ahora, creemos un valor ambiental que necesitaremos para nuestra aplicación. Vuelva a su editor de código y cree un archivo en la raíz de su proyecto. .env 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 una vez que realicemos las llamadas a la API para recuperar los datos del OneEntry CMS. process.env.API_KEY 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 en la raíz del proyecto y edítelo de la siguiente manera: next.config.js 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 en el directorio que se encuentra en la carpeta y cambie el contenido del archivo a lo siguiente: globals.css app src @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 dentro del directorio de la . Cree un archivo dentro de la carpeta recién creada e incluya el código: interfaces app data.tsx 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 dentro del directorio de la con un archivo dentro: services app fetchData.tsx 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 recuperará los datos sobre todas las páginas que creamos en OneEntry CMS. getPages La función obtendrá los datos de una colección específica de productos según el parámetro . Pasaremos el parámetro cuando importemos la función a la página de productos. getProducts category La función obtendrá los datos según la 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. getProduct id Tenga en cuenta que utilizamos para acceder a la clave API que definimos en el archivo anteriormente para autenticar el acceso a OneEntry CMS. process.env.API_KEY .env Crear funciones auxiliares Además, mientras todavía estamos en la carpeta , creemos otro archivo nuevo dentro de ella llamado que incluirá pequeñas funciones de utilidad: services helpers.tsx 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 sumará los precios de los productos agregados al carrito y devolverá el valor total. calculateTotal El detectará si los artículos individuales en la ruta de vista previa ya se han agregado al carrito. boughtStatus detectará la posición del artículo en la matriz de los productos que se han agregado al carrito. cartIndex Creando componentes Vuelva al directorio y cree una nueva carpeta de dentro de él. app components 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 e incluya el siguiente código: Header.tsx 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 e incluya el siguiente código: Footer.tsx 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 e incluya el siguiente código: Text.tsx 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 e incluya el siguiente código: Card.tsx 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 e incluya el siguiente código: Preview.tsx "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 e incluya el siguiente código: Order.tsx "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 y los mostrará en la pantalla mediante el método . cardItems map La cantidad total de los elementos renderizados se calculará mediante la función , que importamos del archivo . calculateTotal helpers.tsx Componente AddToCart Abra el archivo e incluya el siguiente código: AddToCart.tsx "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 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". isPurchased La función de clic de la función agregará o eliminará el producto de la matriz de elementos según el estado anterior. handleButtonClick 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 en el directorio y edite su contenido de la siguiente manera: page.tsx app 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 para obtener los datos del encabezado. getPages Luego usamos la función para recuperar los datos de la página Hero y luego los convertimos en un objeto para facilitar el procesamiento. getValues pageContent 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 en el directorio y dentro de ella, un archivo . [category] app 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 de la URL, que luego pasamos a la función , para describir qué categoría de productos necesitamos recuperar en función de la página del sitio que se visita. category getProducts Una vez recibidos los datos, creamos una matriz de objetos que consta de todos los atributos necesarios para la página para facilitar su procesamiento. productItems Luego lo recorremos mediante el método del y lo representamos en la pantalla pasando accesorios al componente Tarjeta que importamos desde la carpeta del . map component Vista previa de la pàgina Dentro de la carpeta , cree otra carpeta llamada . [category] [productId] Abra la carpeta recién creada y cree un archivo dentro de ella con el código: page.tsx 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 de la URL, que luego pasamos a la función , para especificar qué producto necesitamos recuperar en función del producto que se ve en la página de vista previa. productId getProduct Una vez recibidos los datos, creamos un objeto que consta de todos los atributos necesarios para pasarlos al componente Vista previa como accesorios. productItem También obtenemos el parámetro , 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. category Página del carrito Finalmente, cree un nuevo de carpetas en el directorio . cart app Ábralo, cree un nuevo archivo dentro de él con el siguiente código: page.tsx 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 para iniciarlo nuevamente y acceda para verlo. npm run dev a localhost:3000 Su proyecto ahora debería verse así: 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 , 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. GitHub 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 , y . Twitter LinkedIn GitHub También publicado aquí