Este é um artigo de parceria patrocinado pela OneEntry CMS .
Construir um aplicativo de comércio eletrônico costuma ser uma tarefa desafiadora. Com tantas alternativas disponíveis, não é fácil escolher uma pilha de tecnologia que atenda aos requisitos do projeto, às necessidades de escalabilidade e à sustentabilidade a longo prazo.
Outro ponto crucial é que os projetos de comércio eletrônico lidam com muitos dados e operações CRUD. Criar um sistema back-end sólido, escalável e seguro pode levar muito tempo, mesmo para os desenvolvedores mais experientes.
Escolhi uma pilha de tecnologia baseada em NextJS, TypeScript, Tailwind CSS e OneEntry CMS. Nós mesmos construiremos um projeto prático de comércio eletrônico para ver como ele funciona em conjunto e como pode ser usado para simplificar o gerenciamento de conteúdo.
O código deste projeto estará disponível no repositório GitHub .
NextJS é uma estrutura React para construção de aplicativos web rápidos e eficientes, que vem com recursos como renderização de cliente e servidor, busca de dados, manipuladores de rota, middleware, otimizações integradas e muito mais.
TypeScript adiciona digitação estática ao JavaScript, o que torna mais fácil detectar e corrigir erros em projetos escalonáveis como comércio eletrônico. Ele também aumenta a produtividade por meio de recursos como preenchimento automático e assistência à refatoração.
Tailwind CSS acelera a parte de estilo dos aplicativos da web, permitindo que os desenvolvedores estilizem os elementos dentro da marcação sem a necessidade de alternar entre arquivos CSS externos e criar os nomes de classe para cada um.
OneEntry CMS é um sistema de gerenciamento de conteúdo headless com uma interface fácil de usar, back-end facilmente escalonável, API rápida e documentação clara para aumentar sua produtividade na criação de conteúdo de site e experiência de gerenciamento.
A página de destino exibirá o título do título, listará os recursos da loja e incluirá a imagem principal.
A primeira seção da loja será dedicada ao Vestuário.
A segunda seção da loja incluirá o Gear.
Cada um dos itens terá uma página de visualização individual com detalhes.
Os itens que já estão no carrinho terão a opção de removê-los.
O carrinho listará todos os itens selecionados e calculará o total.
Primeiro, o usuário precisará se inscrever em uma nova conta. Para fazer isso, navegue até a página inicial do OneEntry e cadastre-se através de sua conta de e-mail.
Depois disso, faça login e você será direcionado para o painel do OneEntry.
Comece criando um novo projeto.
Você receberá o código gratuito para usar o plano de estudos por um mês. Você terá a oportunidade de ativá-lo durante o processo de criação do projeto.
A criação do projeto levará alguns minutos. Quando estiver pronto, o status do projeto mudará para “Em funcionamento” e o indicador de status ficará verde.
Após a criação do projeto, você receberá um e-mail com dados de login para acessar seu portal CMS para criar e armazenar os dados do aplicativo.
Após o login, você poderá criar sua primeira página.
Navegue até Gerenciamento de Conteúdo, clique em Criar uma nova página e preencha todos os dados necessários - tipos de páginas, título da página, ULR da página e nome do item de menu.
Todos os dados são salvos automaticamente ao entrar.
Crie 4 páginas diferentes para Casa, Roupas, Equipamentos e Carrinho. Depois de criadas, as páginas deverão ficar como na imagem abaixo.
A seguir, precisamos criar a estrutura de dados que iremos armazenar. No OneEntry CMS, isso é conseguido criando os atributos para os dados.
Navegue até Configurações e escolha Atributos no menu horizontal. Crie um conjunto de atributos para a página inicial fornecendo o nome, o marcador e o tipo:
Depois de criado, ficará como na imagem abaixo:
Da mesma forma, vamos criar dois conjuntos de atributos separados para roupas e equipamentos. Depois de criado, o resultado deve ser semelhante ao da imagem abaixo.
Agora, vamos definir atributos específicos para cada conjunto.
Com base no conteúdo que incluímos anteriormente no wireframe da seção Home, queremos exibir o título, a descrição e a imagem.
Clique no item de engrenagem para Home e crie os seguintes nomes de atributos, marcadores e tipos de atributos conforme mostrado na lista abaixo.
Agora volte e clique no ícone de engrenagem para Roupas.
Os atributos desta página serão um pouco diferentes, pois queremos exibir o título, subtítulo, descrição, imagem e preço do produto.
Esta é a aparência da estrutura de atributos:
A seguir, faça o mesmo para a página Gear, que usará a mesma estrutura:
Nesta fase do projeto já definimos a estrutura do conteúdo e estamos prontos para começar a criar o próprio conteúdo.
Navegue até a seção Gerenciamento de conteúdo onde você criou anteriormente todas as páginas do site:
Clique no botão de edição para Home. Depois disso, clique na aba Atributos no menu Horizontal:
Selecione Home para o conjunto de atributos. Isso carregará todos os atributos que criamos anteriormente em Configurações da página inicial.
Agora preencha alguns dados de amostra que deseja exibir na página inicial.
Agora, vamos adicionar algum conteúdo para nossas páginas de Roupas e Equipamentos.
Como selecionamos o tipo de página como Catálogo, selecione Catálogo no menu esquerdo e ambas as páginas deverão estar visíveis lá:
Agora, clique no ícone Adicionar para Roupas e adicione alguns itens.
Primeiro, adicione o cabeçalho do produto que deseja adicionar.
Agora mude para a guia Atributos, selecione Roupas para o Conjunto de atributos e preencha os dados necessários.
Volte ao menu Catálogo e mais alguns itens para roupas e equipamentos. Para nosso aplicativo de demonstração, adicionei 4 itens conforme mostrado na captura de tela abaixo:
Todos os dados criados no OneEntry CMS estão protegidos, portanto teremos que criar um token privado para podermos acessá-los.
Para fazer isso, navegue até Configurações e selecione Tokens de aplicativo. Insira o nome do aplicativo e a data de expiração e clique em Criar. Isso irá gerar uma chave de API exclusiva.
Clique no ícone de visualização na lista de ações e você poderá ver a chave. Copie-o para a área de transferência, pois precisaremos dele na próxima seção do tutorial.
Nesta seção do tutorial, começaremos a trabalhar com o código e configuraremos o projeto NextJS para funcionar com OneEntry CMS.
Abra o terminal e execute o comando npx create-next-app@latest
.
A CLI iniciará o assistente de configuração. Insira o nome do seu projeto e selecione todos os valores padrão conforme mostrado abaixo:
Aguarde um minuto para que a configuração seja concluída e você receberá uma notificação quando o aplicativo NextJS for criado.
Depois disso, altere o diretório para a pasta recém-criada usando o comando cd winter-sports
e execute npm run dev
para iniciar o servidor do desenvolvedor.
Para acessá-lo, clique no link fornecido no terminal ou abra seu navegador e navegue até http://localhost:3000 manualmente.
Você deverá ver a página inicial do servidor do desenvolvedor NextJS:
Agora, vamos criar um valor ambiental que precisaremos para nosso aplicativo. Volte para o seu editor de código e crie um arquivo .env
na raiz do seu projeto.
Cole a chave de API que você copiou anteriormente na área de transferência da seguinte maneira:
API_KEY=your-api-code-from-oneentry
Isso nos permitirá acessar a chave via process.env.API_KEY
assim que fizermos as chamadas de API para buscar os dados do OneEntry CMS.
Também precisamos configurar o NextJS, para que possamos incluir a mídia de um domínio externo. Precisaremos disso para acessar imagens do OneEntry CMS.
Abra o arquivo next.config.js
na raiz do projeto e edite-o da seguinte forma:
const nextConfig = { images: { remotePatterns: [ { hostname: "ecommerce.oneentry.cloud", }, ], }, }; module.exports = nextConfig;
Por fim, precisaremos redefinir o estilo padrão do Tailwind para o aplicativo, pois escreveremos todos os estilos do zero.
Abra o arquivo globals.css
no diretório app
localizado na pasta src
e altere o conteúdo do arquivo para o seguinte:
@tailwind base; @tailwind components; @tailwind utilities;
Como trabalharemos com TypeScript, precisaremos definir quais tipos de dados usaremos em nossa aplicação.
Poderíamos fazer isso dentro das páginas e componentes, mas para manter o código mais limpo e evitar repetições, crie uma nova pasta interfaces
dentro do diretório app
. Crie um arquivo data.tsx
dentro da pasta recém-criada e inclua o 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; }
Os dados de produtos e páginas terão tipos para sua estrutura de dados de renderização de front-end e a resposta da API por meio do método de busca.
Além disso, definimos os tipos de dados para os dados dos parâmetros de URL e o renderizador de texto para os dados recebidos dos campos de entrada de texto no CMS.
Agora, vamos criar algumas funções que usaremos para nos comunicarmos com o OneEntry CMS para buscar os dados das páginas e produtos.
Novamente, poderíamos fazer isso em cada arquivo, mas para manter o código mais limpo, vamos criar uma nova pasta services
dentro do diretório app
com um arquivo fetchData.tsx
dentro dela:
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(); }
A função getPages
irá buscar os dados sobre todas as páginas que criamos no OneEntry CMS.
A função getProducts
buscará os dados de uma coleção específica de produtos com base no parâmetro category
. Passaremos o parâmetro quando importarmos a função para a página de produtos.
A função getProduct
irá buscar os dados com base no id
do produto que abrimos. Passaremos o parâmetro quando importarmos a função para a página de visualização de qualquer produto específico.
Observe que usamos process.env.API_KEY
para acessar a chave API que definimos no arquivo .env
anteriormente para autenticar o acesso ao OneEntry CMS.
Além disso, enquanto ainda estamos na pasta services
, vamos criar outro novo arquivo dentro dela chamado helpers.tsx
que incluirá pequenas funções utilitárias:
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); }
A função calculateTotal
irá somar os preços dos produtos adicionados ao carrinho e retornar o valor total.
O boughtStatus
detectará se os itens individuais na rota de visualização já foram adicionados ao carrinho.
O cartIndex
detectará a posição do item na matriz dos produtos que foram adicionados ao carrinho.
Navegue de volta para o diretório app
e crie uma nova pasta de components
dentro dele.
Abra a pasta recém-criada e inclua sete arquivos separados nela: Header.tsx
, Footer.tsx
, Text.tsx
, Card.tsx
, Preview.tsx
, Order.tsx
, AddToCart.tsx
.
Componente de cabeçalho
Abra o arquivo Header.tsx
e inclua o seguinte 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 o cabeçalho, exibimos o nome da empresa e percorremos os links de navegação que obteremos da API assim que o componente for importado para as páginas.
Criamos um layout de duas colunas e posicionamos ambos os elementos em lados opostos da tela horizontalmente para obter a aparência típica de navegação.
Componente de rodapé
Abra o arquivo Footer.tsx
e inclua o seguinte 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> ); }
No rodapé, incluímos o exemplo do nome da empresa e os direitos do conteúdo do ano em curso. Centralizamos o conteúdo e adicionamos algum preenchimento.
Componente de texto
Abra o arquivo Text.tsx
e inclua o seguinte código:
import { TextProps } from "../interfaces/data"; export default function Text({ className, text }: TextProps) { return ( <div className={className} dangerouslySetInnerHTML={{ __html: text }} /> ); }
O componente Texto renderizará os dados de texto que recebemos do OneEntry CMS e os exibirá corretamente em nosso aplicativo sem tags HTML.
Componente de cartão
Abra o arquivo Card.tsx
e inclua o seguinte 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> ); }
No componente cartão, exibimos imagem, título, subtítulo e preço de cada produto. Mapearemos todos os itens assim que forem importados para as páginas.
A imagem será exibida na parte superior do cartão, seguida do título e da descrição, e o preço no canto inferior direito do componente.
Componente de visualização
Abra o arquivo Preview.tsx
e inclua o seguinte 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> ); }
O componente de visualização será usado para exibir mais informações sobre cada produto assim que o usuário clicar nele.
Exibiremos a imagem do produto, título, preço e descrição. O layout será dividido em 2 colunas, sendo a imagem exibida na coluna da esquerda e o restante do conteúdo na direita.
Componente de pedido
Abra o arquivo Order.tsx
e inclua o seguinte 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> ); }
O componente de pedido listará todos os itens que o usuário adicionou ao carrinho. Para cada item serão exibidos imagem, título, subtítulo e preço.
Depois que o componente for renderizado, o aplicativo acessará todos os itens atualmente no carrinho, os definirá para a variável de estado cardItems
e os renderizará na tela por meio do método map
.
A quantidade total de itens renderizados será calculada por meio da função calculateTotal
, que importamos do arquivo helpers.tsx
.
Componente AddToCart
Abra o arquivo AddToCart.tsx
e inclua o seguinte 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> ); }
O componente addToCart será exibido na página de visualização do produto individual e permitirá ao usuário adicionar o produto ao carrinho de compras.
Após a renderização, a função isPurchased
detectará se o produto já foi adicionado ao carrinho ou não. Se não for o botão renderizado, será exibido "Adicionar ao carrinho", caso contrário, será exibido "Remover do carrinho".
O recurso de clique da função handleButtonClick
adicionará ou removerá o produto da matriz de itens com base no estado acima.
Por fim, vamos importar os componentes que criamos na seção anterior do tutorial e criar a lógica da página para a aplicação.
Pagina inicial
Abra page.tsx
no diretório app
e edite seu conteúdo da seguinte maneira:
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> ); }
Na página inicial, primeiro chamaremos a função getPages
para obter os dados do cabeçalho.
Em seguida, usamos a função getValues
para buscar os dados da página Hero e, em seguida, transformá-los no objeto pageContent
para facilitar o processamento.
Em seguida, renderizamos os componentes de cabeçalho e rodapé importados, bem como passamos os valores necessários para o título, descrição e imagem do herói.
Página de produtos
Crie uma nova pasta [category]
no diretório app
e dentro dela - um arquivo page.tsx
.
O uso de nomes de arquivos específicos é importante, pois é isso que o NextJS usa para lidar com rotas e acessar parâmetros de URL.
Inclua o seguinte código no 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 a página de produtos, primeiro obtemos o parâmetro category
do URL, que posteriormente passamos para a função getProducts
, para descrever qual categoria de produtos precisamos buscar com base em qual página do site é visitada.
Uma vez recebidos os dados, criamos um array de objetos productItems
que consiste em todos os atributos necessários para a página para facilitar o processamento.
Em seguida, percorremos ele por meio do método map
e o renderizamos na tela, passando adereços para o componente Card que importamos da pasta do component
.
Página de visualização
Dentro da pasta [category]
, crie outra pasta chamada [productId]
.
Abra a pasta recém-criada e crie um arquivo page.tsx
dentro dela com o 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á que os usuários vejam mais detalhes de qualquer produto individual assim que clicarem em seus cartões na página de produtos.
Primeiro obtemos o parâmetro productId
do URL, que posteriormente passamos para a função getProduct
, para especificar qual produto precisamos buscar com base em qual produto é visualizado na página de visualização.
Assim que os dados forem recebidos, criamos um objeto productItem
que consiste em todos os atributos necessários para serem passados para o componente Preview como adereços.
Também obtemos o parâmetro category
, pois precisamos passá-lo para o componente Adicionar ao carrinho, para que possamos criar um link válido para o item na página do carrinho.
Página do carrinho
Por fim, crie uma nova pasta cart
no diretório app
.
Abra-o, crie um novo arquivo page.tsx
dentro dele com o seguinte 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> ); }
Primeiro buscamos os dados necessários e depois os passamos para o cabeçalho como adereços.
Em seguida renderizamos o componente Header com a navegação, o componente Order que listará todos os itens que o usuário adicionou ao carrinho e também o componente Footer com o nome da empresa e as informações de copyright.
Parabéns, você fez um projeto funcional!
Primeiro, verifique se o servidor do desenvolvedor ainda está em execução. Caso contrário, execute o comando npm run dev
para iniciá-lo novamente e acesse localhost:3000 para visualizá-lo.
Seu projeto agora deve ficar assim:
Como você pode ver, o conteúdo da seção Home foi obtido com sucesso do conjunto de atributos Home que especificamos nos campos de dados.
Além disso, todos os itens do catálogo OneEntry CMS foram obtidos nas seções Roupas e Equipamentos com todas as informações devidamente renderizadas.
Os usuários também podem visualizar cada produto separadamente em sua página dedicada, graças ao gerenciamento de rotas e parâmetros do produto NextJS.
Além disso, todas as funções e eventos funcionam conforme o esperado, e o usuário pode adicionar e retirar os itens do carrinho de compras, sendo calculado o total.
Neste tutorial, criamos um projeto de comércio eletrônico que permite aos usuários criar, atualizar e excluir páginas do site e seu conteúdo, bem como gerenciar produtos facilmente com uma interface de catálogo fácil de usar, graças ao OneEntry CMS .
O código está disponível no GitHub , então fique à vontade para cloná-lo e adicionar mais funcionalidades para atender às suas necessidades. Você pode adicionar mais seções de menu, estender componentes individuais ou até mesmo adicionar mais componentes para implementar novos recursos.
Esperançosamente, isso será útil para você e você terá uma ideia de como usar o OneEntry CMS como uma solução de back-end, como combiná-lo com o front-end do seu aplicativo e como usar os melhores recursos de NextJS, Typescript e Tailwind .
Certifique-se de receber os melhores recursos, ferramentas, dicas de produtividade e dicas de crescimento de carreira que descobri assinando meu boletim informativo !
Além disso, conecte-se comigo no Twitter , LinkedIn e GitHub !
Também publicado aqui