Dies ist ein Partnerschaftsartikel, der von OneEntry CMS gesponsert wird.
Der Aufbau einer E-Commerce-Anwendung ist oft eine herausfordernde Aufgabe. Bei so vielen verfügbaren Alternativen ist es nicht einfach, einen Technologie-Stack auszuwählen, der den Anforderungen, Skalierbarkeitsanforderungen und der langfristigen Nachhaltigkeit des Projekts entspricht.
Ein weiterer entscheidender Punkt ist, dass E-Commerce-Projekte mit vielen Daten und CRUD-Operationen zu tun haben. Die Erstellung eines soliden, skalierbaren und sicheren Backend-Systems kann selbst für die erfahrensten Entwickler viel Zeit in Anspruch nehmen.
Ich habe einen Tech-Stack ausgewählt, der auf NextJS, TypeScript, Tailwind CSS und OneEntry CMS basiert. Wir werden selbst ein praktisches E-Commerce-Projekt aufbauen, um zu sehen, wie es zusammenspielt und wie es zur Vereinfachung des Content-Managements genutzt werden kann.
Der Code für dieses Projekt wird im GitHub-Repository verfügbar sein.
NextJS ist ein React-Framework zum Erstellen schneller und effizienter Webanwendungen, das Funktionen wie Client- und Server-Rendering, Datenabruf, Routenhandler, Middleware, integrierte Optimierungen und vieles mehr bietet.
TypeScript fügt JavaScript statische Typisierung hinzu, was es einfacher macht, Fehler für skalierbare Projekte wie E-Commerce zu erkennen und zu beheben. Darüber hinaus steigert es die Produktivität durch Funktionen wie automatische Vervollständigung und Refactoring-Unterstützung.
Tailwind CSS beschleunigt den Styling-Teil der Web-Apps und ermöglicht es Entwicklern, die Elemente innerhalb des Markups zu formatieren, ohne zwischen externen CSS-Dateien wechseln und sich jeweils die Klassennamen ausdenken zu müssen.
OneEntry CMS ist ein Headless-Content-Management-System mit einer benutzerfreundlichen Oberfläche, einem leicht skalierbaren Backend, einer schnellen API und einer klaren Dokumentation, um Ihre Produktivität bei der Erstellung und Verwaltung von Website-Inhalten zu steigern.
Auf der Zielseite wird der Überschriftentitel angezeigt, die Funktionen des Shops aufgelistet und das Heldenbild eingefügt.
Der erste Shop-Bereich ist der Bekleidung gewidmet.
Der zweite Shop-Bereich wird die Ausrüstung umfassen.
Für jedes Element gibt es eine eigene Vorschauseite mit Details.
Für Artikel, die sich bereits im Warenkorb befinden, besteht die Möglichkeit, sie zu entfernen.
Der Warenkorb listet alle ausgewählten Artikel auf und berechnet die Gesamtsumme.
Zunächst muss sich der Benutzer für ein neues Konto anmelden. Navigieren Sie dazu zur OneEntry-Homepage und melden Sie sich über Ihr E-Mail-Konto an .
Melden Sie sich anschließend an und Sie werden zum OneEntry-Dashboard weitergeleitet.
Beginnen Sie mit der Erstellung eines neuen Projekts.
Sie erhalten den kostenlosen Code, um den Studienplan einen Monat lang zu nutzen. Sie haben die Möglichkeit, es während des Erstellungsprozesses des Projekts zu aktivieren.
Die Erstellung des Projekts wird einige Minuten dauern. Sobald es fertig ist, ändert sich der Projektstatus auf „In Arbeit“ und die Statusanzeige leuchtet grün.
Nachdem das Projekt erstellt wurde, erhalten Sie eine E-Mail mit Anmeldedaten, um auf Ihr CMS-Portal zuzugreifen und die Daten für die App zu erstellen und zu speichern.
Nach dem Login können Sie Ihre erste Seite erstellen.
Navigieren Sie zu Content Management, klicken Sie auf Neue Seite erstellen und geben Sie alle erforderlichen Daten ein – Seitentypen, Seitentitel, Seiten-ULR und Name des Menüelements.
Alle Daten werden bei der Eingabe automatisch gespeichert.
Erstellen Sie 4 verschiedene Seiten für Zuhause, Kleidung, Ausrüstung und Warenkorb. Nach der Erstellung sollten die Seiten wie im Screenshot unten aussehen.
Als nächstes müssen wir die Datenstruktur erstellen, die wir speichern möchten. Im OneEntry CMS wird dies durch die Erstellung der Attribute für die Daten erreicht.
Navigieren Sie zu „Einstellungen“ und wählen Sie im horizontalen Menü „Attribute“. Erstellen Sie einen Attributsatz für die Startseite unter Angabe des Namens, der Markierung und des Typs:
Nach der Erstellung sieht es wie im folgenden Screenshot aus:
Erstellen wir auf ähnliche Weise zwei separate Attributsätze für Kleidung und Ausrüstung. Nach der Erstellung sollte das Ergebnis wie im Screenshot unten aussehen.
Definieren wir nun für jeden Satz spezifische Attribute.
Basierend auf dem Inhalt, den wir zuvor im Wireframe des Abschnitts „Home“ eingefügt haben, möchten wir den Titel, die Beschreibung und das Bild anzeigen.
Klicken Sie auf das Zahnradelement für „Home“ und erstellen Sie die folgenden Attributnamen, Markierungen und Attributtypen, wie in der Liste unten gezeigt.
Gehen Sie nun zurück und klicken Sie auf das Zahnradsymbol für Kleidung.
Die Attribute für diese Seite werden etwas anders sein, da wir den Produkttitel, den Untertitel, die Beschreibung, das Bild und den Preis anzeigen möchten.
So würde die Attributstruktur aussehen:
Machen Sie als Nächstes dasselbe für die Gear-Seite, die dieselbe Struktur verwenden wird:
In dieser Phase des Projekts haben wir bereits die Inhaltsstruktur definiert und sind bereit, mit der Erstellung des Inhalts selbst zu beginnen.
Navigieren Sie zum Abschnitt „Content Management“, in dem Sie zuvor alle Ihre Seiten für die Website erstellt haben:
Klicken Sie auf die Schaltfläche „Bearbeiten“ für „Startseite“. Klicken Sie anschließend im Menü „Horizontal“ auf die Registerkarte „Attribute“:
Wählen Sie Home für den Attributsatz aus. Dadurch werden alle Attribute geladen, die wir zuvor in den Einstellungen für die Startseite erstellt haben.
Geben Sie nun einige Beispieldaten ein, die auf der Startseite angezeigt werden sollen.
Fügen wir nun einige Inhalte für unsere Seiten „Bekleidung“ und „Ausrüstung“ hinzu.
Da wir den Seitentyp „Katalog“ ausgewählt haben, wählen Sie im linken Menü „Katalog“ aus. Beide Seiten sollten dort sichtbar sein:
Klicken Sie nun auf das Symbol „Hinzufügen“ für Kleidung und fügen Sie einige Artikel hinzu.
Fügen Sie zunächst die Kopfzeile für das Produkt hinzu, das Sie hinzufügen möchten.
Wechseln Sie nun zur Registerkarte „Attribute“, wählen Sie als Attributsatz „Kleidung“ aus und geben Sie die erforderlichen Daten ein.
Gehen Sie zurück zum Katalogmenü und sehen Sie ein paar weitere Artikel für Kleidung und Ausrüstung. Für unsere Demo-App habe ich 4 Elemente hinzugefügt, wie im Screenshot unten gezeigt:
Alle im OneEntry CMS erstellten Daten sind geschützt, daher müssen wir einen privaten Token erstellen, um darauf zugreifen zu können.
Navigieren Sie dazu zu „Einstellungen“ und wählen Sie „App-Tokens“ aus. Geben Sie den App-Namen und das Ablaufdatum ein und klicken Sie auf Erstellen. Dadurch wird ein eindeutiger API-Schlüssel generiert.
Klicken Sie in der Aktionsliste auf das Ansichtssymbol, um den Schlüssel anzuzeigen. Kopieren Sie es in die Zwischenablage, da wir es im nächsten Abschnitt des Tutorials benötigen.
In diesem Abschnitt des Tutorials beginnen wir mit der Arbeit mit dem Code und konfigurieren das NextJS-Projekt für die Zusammenarbeit mit OneEntry CMS.
Öffnen Sie das Terminal und führen Sie den Befehl npx create-next-app@latest
aus.
Die CLI startet den Setup-Assistenten. Geben Sie den Namen Ihres Projekts ein und wählen Sie alle Standardwerte aus, wie unten gezeigt:
Nehmen Sie sich eine Minute Zeit, um die Einrichtung abzuschließen, und Sie erhalten eine Benachrichtigung, wenn die NextJS-App erstellt wurde.
Wechseln Sie anschließend mit dem Befehl cd winter-sports
das Verzeichnis in den neu erstellten Ordner und führen Sie dann npm run dev
aus, um den Entwicklerserver zu starten.
Um darauf zuzugreifen, klicken Sie auf den Link auf dem Terminal oder öffnen Sie Ihren Webbrowser und navigieren Sie manuell zu http://localhost:3000 .
Die Zielseite des NextJS-Entwicklerservers sollte angezeigt werden:
Lassen Sie uns nun einen Umweltwert erstellen, den wir für unsere App benötigen. Wechseln Sie zurück zu Ihrem Code-Editor und erstellen Sie eine .env
Datei im Stammverzeichnis Ihres Projekts.
Fügen Sie den API-Schlüssel, den Sie zuvor in die Zwischenablage kopiert haben, wie folgt ein:
API_KEY=your-api-code-from-oneentry
Dadurch können wir über process.env.API_KEY
auf den Schlüssel zugreifen, sobald wir die API-Aufrufe durchführen, um die Daten vom OneEntry-CMS abzurufen.
Wir müssen auch NextJS konfigurieren, damit wir die Medien von einer externen Domäne einbinden können. Wir benötigen dies, um auf Bilder von OneEntry CMS zuzugreifen.
Öffnen Sie die Datei next.config.js
im Projektstammverzeichnis und bearbeiten Sie sie wie folgt:
const nextConfig = { images: { remotePatterns: [ { hostname: "ecommerce.oneentry.cloud", }, ], }, }; module.exports = nextConfig;
Schließlich müssen wir den Tailwind-Standardstil für die App zurücksetzen, da wir alle Stile von Grund auf neu schreiben werden.
Öffnen Sie die Datei globals.css
im app
Verzeichnis im Ordner src
und ändern Sie den Inhalt der Datei wie folgt:
@tailwind base; @tailwind components; @tailwind utilities;
Da wir mit TypeScript arbeiten, müssen wir definieren, welche Datentypen wir in unserer Anwendung verwenden werden.
Wir könnten dies innerhalb der Seiten und Komponenten tun, aber um den Code sauberer zu halten und Wiederholungen zu vermeiden, erstellen Sie einen neuen Ordner „ interfaces
im app
Verzeichnis. Erstellen Sie eine Datei data.tsx
im neu erstellten Ordner und fügen Sie den Code ein:
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; }
Sowohl Produkte als auch Seitendaten verfügen über Typen für ihre Front-End-Rendering-Datenstruktur und die Antwort von der API über die Abrufmethode.
Außerdem haben wir die Datentypen für die Daten aus den URL-Parametern und den Textrenderer für die Daten definiert, die aus den Texteingabefeldern im CMS empfangen werden.
Lassen Sie uns nun einige Funktionen erstellen, die wir zur Kommunikation mit OneEntry CMS verwenden, um die Daten für die Seiten und Produkte abzurufen.
Auch dies könnten wir in jeder Datei tun, aber um den Code sauberer zu halten, erstellen wir einen neuen Ordner „ services
im app
Verzeichnis mit einer Datei fetchData.tsx
darin:
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(); }
Die Funktion getPages
ruft die Daten aller Seiten ab, die wir im OneEntry CMS erstellt haben.
Die Funktion getProducts
ruft die Daten für eine bestimmte Produktsammlung basierend auf dem category
ab. Wir übergeben den Parameter, wenn wir die Funktion in die Produktseite importieren.
Die Funktion getProduct
ruft die Daten basierend auf der id
des von uns geöffneten Produkts ab. Wir übergeben den Parameter, wenn wir die Funktion in die Vorschauseite für ein bestimmtes Produkt importieren.
Beachten Sie, dass wir process.env.API_KEY
verwendet haben, um auf den API-Schlüssel zuzugreifen, den wir zuvor in der .env
Datei definiert haben, um den Zugriff für das OneEntry CMS zu authentifizieren.
Während wir uns noch im services
Ordner befinden, erstellen wir darin eine weitere neue Datei mit dem Namen helpers.tsx
, die kleine Hilfsfunktionen enthält:
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); }
Die Funktion calculateTotal
addiert die Preise der zum Warenkorb hinzugefügten Produkte und gibt den Gesamtwert zurück.
Der boughtStatus
erkennt, ob die einzelnen Artikel in der Vorschauroute bereits zum Warenkorb hinzugefügt wurden.
Der cartIndex
erkennt die Position des Artikels im Array für die Produkte, die dem Warenkorb hinzugefügt wurden.
Navigieren Sie zurück zum app
Verzeichnis und erstellen Sie darin einen neuen Ordner components
.
Öffnen Sie den neu erstellten Ordner und fügen Sie sieben separate Dateien darin ein: Header.tsx
, Footer.tsx
, Text.tsx
, Card.tsx
, Preview.tsx
, Order.tsx
, AddToCart.tsx
.
Header-Komponente
Öffnen Sie die Datei Header.tsx
und fügen Sie den folgenden Code ein:
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> ); }
Für die Kopfzeile haben wir den Firmennamen angezeigt und die Navigationslinks durchlaufen, die wir von der API erhalten, sobald die Komponente in Seiten importiert wird.
Wir haben ein zweispaltiges Layout erstellt und beide Elemente horizontal an den gegenüberliegenden Seiten des Bildschirms positioniert, um den typischen Navigationslook zu erreichen.
Fußzeilenkomponente
Öffnen Sie die Datei Footer.tsx
und fügen Sie den folgenden Code ein:
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> ); }
In der Fußzeile haben wir den Beispielnamen des Unternehmens und die Inhaltsrechte mit der aktuellen Jahreszahl eingefügt. Wir haben den Inhalt zentriert und etwas Polsterung hinzugefügt.
Textkomponente
Öffnen Sie die Datei Text.tsx
und fügen Sie den folgenden Code ein:
import { TextProps } from "../interfaces/data"; export default function Text({ className, text }: TextProps) { return ( <div className={className} dangerouslySetInnerHTML={{ __html: text }} /> ); }
Die Textkomponente rendert die Textdaten, die wir vom OneEntry CMS erhalten, und zeigt sie ordnungsgemäß in unserer Anwendung ohne HTML-Tags an.
Kartenkomponente
Öffnen Sie die Datei Card.tsx
und fügen Sie den folgenden Code ein:
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> ); }
In der Kartenkomponente haben wir für jedes Produkt das Bild, den Titel, den Untertitel und den Preis angezeigt. Wir werden alle Elemente zuordnen, sobald sie in die Seiten importiert werden.
Das Bild wird oben auf der Karte angezeigt, gefolgt vom Titel und der Beschreibung sowie dem Preis unten rechts auf der Komponente.
Vorschau der Komponente
Öffnen Sie die Datei Preview.tsx
und fügen Sie den folgenden Code ein:
"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> ); }
Die Vorschaukomponente wird verwendet, um weitere Informationen zu jedem Produkt anzuzeigen, sobald der Benutzer darauf klickt.
Wir zeigen das Produktbild, den Titel, den Preis und die Beschreibung an. Das Layout wird in zwei Spalten unterteilt, wobei das Bild in der linken Spalte und der Rest des Inhalts in der rechten Spalte angezeigt wird.
Bestellkomponente
Öffnen Sie die Datei Order.tsx
und fügen Sie den folgenden Code ein:
"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> ); }
In der Bestellkomponente werden alle Artikel aufgelistet, die der Benutzer dem Warenkorb hinzugefügt hat. Für jeden Artikel werden Bild, Titel, Untertitel und Preis angezeigt.
Sobald die Komponente gerendert ist, greift die App auf alle derzeit im Warenkorb befindlichen Artikel zu, setzt sie auf die Statusvariable cardItems
und rendert sie über die map
auf dem Bildschirm.
Die Gesamtmenge der gerenderten Elemente wird über die Funktion calculateTotal
berechnet, die wir aus der Datei helpers.tsx
importiert haben.
AddToCart-Komponente
Öffnen Sie die Datei AddToCart.tsx
und fügen Sie den folgenden Code ein:
"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> ); }
Die addToCart-Komponente wird auf der Vorschauseite des einzelnen Produkts angezeigt und ermöglicht es dem Benutzer, das Produkt in den Warenkorb zu legen.
Beim Rendern erkennt die Funktion isPurchased
, ob das Produkt bereits zuvor zum Warenkorb hinzugefügt wurde oder nicht. Wenn es sich nicht um die gerenderte Schaltfläche handelt, wird „In den Warenkorb“ angezeigt, andernfalls wird „Aus dem Warenkorb entfernen“ angezeigt.
Die Funktion handleButtonClick
zum Klicken fügt das Produkt basierend auf dem obigen Status dem Array „Artikel“ hinzu oder entfernt es daraus.
Abschließend importieren wir die Komponenten, die wir im vorherigen Abschnitt des Tutorials erstellt haben, und erstellen die Seitenlogik für die Anwendung.
Startseite
Öffnen Sie page.tsx
im app
Verzeichnis und bearbeiten Sie den Inhalt wie folgt:
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> ); }
Auf der Startseite rufen wir zunächst die Funktion getPages
auf, um die Daten für den Header abzurufen.
Dann verwenden wir die Funktion getValues
, um die Hero-Seitendaten abzurufen und sie dann zur einfacheren Verarbeitung in ein pageContent
Objekt umzuwandeln.
Anschließend rendern wir die importierten Kopf- und Fußzeilenkomponenten und übergeben die erforderlichen Werte für den Heldentitel, die Beschreibung und das Bild.
Produktseite
Erstellen Sie einen neuen Ordner [category]
im app
Verzeichnis und darin eine Datei page.tsx
.
Die Verwendung spezifischer Dateinamen ist wichtig, da NextJS diese zur Verarbeitung von Routen und zum Zugriff auf URL-Parameter verwendet.
Fügen Sie den folgenden Code in die page.tsx
ein:
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> ); }
Für die Produktseite erhalten wir zunächst den category
von der URL, den wir dann an die Funktion getProducts
übergeben, um zu beschreiben, welche Kategorie der Produkte wir basierend auf der besuchten Seite der Website abrufen müssen.
Sobald die Daten empfangen wurden, erstellen wir ein Array von Objekten productItems
, das zur einfacheren Verarbeitung alle notwendigen Attribute für die Seite enthält.
Dann durchlaufen wir es mit der map
Methode und rendern es auf dem Bildschirm, indem wir Requisiten an die Card-Komponente übergeben, die wir aus dem component
importiert haben.
Vorschauseite
Erstellen Sie im Ordner [category]
einen weiteren Ordner mit dem Namen [productId]
.
Öffnen Sie den neu erstellten Ordner und erstellen Sie darin eine Datei page.tsx
mit dem Code:
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> ); }
Auf dieser Seite können Benutzer weitere Details zu jedem einzelnen Produkt anzeigen, sobald sie auf der Produktseite auf ihre Karten klicken.
Wir rufen zunächst den Parameter productId
von der URL ab, den wir dann an die Funktion getProduct
übergeben, um abhängig davon, welches Produkt auf der Vorschauseite angezeigt wird, anzugeben, welches Produkt wir abrufen müssen.
Sobald die Daten empfangen wurden, erstellen wir ein Objekt productItem
, das aus allen notwendigen Attributen besteht, die als Requisiten an die Preview-Komponente übergeben werden.
Wir erhalten auch den category
, da wir ihn an die Komponente „Zum Warenkorb hinzufügen“ übergeben müssen, damit wir einen gültigen Link für den Artikel auf der Warenkorbseite erstellen können.
Warenkorbseite
Erstellen Sie abschließend einen neuen Ordner cart
im app
Verzeichnis.
Öffnen Sie es und erstellen Sie darin eine neue Datei page.tsx
mit dem folgenden Code:
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> ); }
Wir haben zuerst die notwendigen Daten abgerufen und sie dann als Requisiten an den Header übergeben.
Dann haben wir die Header-Komponente mit der Navigation gerendert, die Order-Komponente, die alle Artikel auflistet, die der Benutzer dem Warenkorb hinzugefügt hat, und auch die Footer-Komponente mit dem Firmennamen und den Copyright-Informationen.
Herzlichen Glückwunsch, Sie haben ein funktionierendes Projekt erstellt!
Überprüfen Sie zunächst, ob der Entwicklerserver noch läuft. Ist dies nicht der Fall, führen Sie den Befehl npm run dev
aus, um es erneut zu starten, und greifen Sie auf localhost:3000 zu, um es anzuzeigen.
Ihr Projekt sollte nun so aussehen:
Wie Sie sehen können, wurde der Inhalt des Home-Abschnitts erfolgreich aus dem Home-Attributsatz abgerufen, den wir in den Datenfeldern angegeben haben.
Außerdem wurden alle Artikel aus dem OneEntry CMS-Katalog in den Abschnitten „Kleidung“ und „Ausrüstung“ abgerufen, wobei alle Informationen ordnungsgemäß wiedergegeben wurden.
Dank der Routenverwaltung und Produktparameter von NextJS können Benutzer auch jedes Produkt einzeln auf einer speziellen Seite in der Vorschau anzeigen.
Außerdem funktionieren alle Funktionen und Ereignisse wie erwartet und der Benutzer kann die Artikel zum Warenkorb hinzufügen und daraus entfernen, wobei die Gesamtsumme berechnet wird.
In diesem Tutorial haben wir ein E-Commerce-Projekt erstellt, das es Benutzern dank OneEntry CMS ermöglicht, Website-Seiten und deren Inhalte zu erstellen, zu aktualisieren und zu löschen sowie Produkte einfach über eine benutzerfreundliche Katalogoberfläche zu verwalten.
Der Code ist auf GitHub verfügbar. Sie können ihn also gerne klonen und je nach Bedarf weitere Funktionen hinzufügen. Sie könnten weitere Menüabschnitte hinzufügen, einzelne Komponenten erweitern oder sogar weitere Komponenten hinzufügen, um neue Funktionen zu implementieren.
Hoffentlich ist dies für Sie nützlich und Sie erhalten einen Einblick in die Verwendung von OneEntry CMS als Backend-Lösung, wie Sie es mit dem Frontend Ihrer Anwendung koppeln und wie Sie die besten Funktionen von NextJS, Typescript und Tailwind nutzen .
Stellen Sie sicher, dass Sie die besten Ressourcen, Tools, Produktivitätstipps und Tipps zur Karriereentwicklung erhalten, die ich entdecken kann, indem Sie meinen Newsletter abonnieren!
Vernetzen Sie sich auch mit mir auf Twitter , LinkedIn und GitHub !
Auch hier veröffentlicht