giriiş Bu, sponsor olduğu bir ortaklık makalesidir. OneEntry CMS'nin Bir e-Ticaret uygulaması oluşturmak genellikle zorlu bir iştir. Bu kadar çok alternatif varken projenin gereksinimlerine, ölçeklenebilirlik ihtiyaçlarına ve uzun vadeli sürdürülebilirliğe uygun bir teknoloji yığını seçmek kolay değil. Bir diğer önemli nokta ise e-Ticaret projelerinin çok fazla veri ve CRUD işlemiyle uğraşmasıdır. Sağlam, ölçeklenebilir ve güvenli bir arka uç sistemi oluşturmak, çoğu deneyimli geliştirici için bile çok zaman alabilir. NextJS, TypeScript, Tailwind CSS ve OneEntry CMS'yi temel alan bir teknoloji yığını seçtim. Birlikte nasıl çalıştığını ve içerik yönetimini basitleştirmek için nasıl kullanılabileceğini görmek için kendimiz pratik bir e-Ticaret projesi oluşturacağız. Bu projenin kodu mevcut olacak. GitHub deposunda Tech Stack Seçimi istemci ve sunucu oluşturma, veri getirme, rota işleyicileri, ara yazılım, yerleşik optimizasyonlar ve çok daha fazlası gibi özelliklerle birlikte gelen, hızlı ve verimli web uygulamaları oluşturmaya yönelik bir React çerçevesidir. NextJS, JavaScript'e statik yazma özelliği ekleyerek e-Ticaret gibi ölçeklenebilir projelerde hataları yakalamayı ve düzeltmeyi kolaylaştırır. Ayrıca otomatik tamamlama ve yeniden düzenleme yardımı gibi özellikler aracılığıyla verimliliği artırır. TypeScript, web uygulamalarının stil oluşturma bölümünü hızlandırarak geliştiricilerin, harici CSS dosyaları arasında geçiş yapmaya ve her biri için sınıf adları bulmaya gerek kalmadan işaretleme içindeki öğelere stil vermelerine olanak tanır. Tailwind CSS, web sitesi içeriği oluşturma ve yönetim deneyiminde üretkenliğinizi artırmak için kullanımı kolay bir arayüze, kolayca ölçeklendirilebilen arka uca, hızlı API'ye ve net belgelere sahip, başsız bir içerik yönetim sistemidir. OneEntry CMS, İçerik ve Tasarım Açılış sayfası başlık başlığını gösterecek, mağazanın özelliklerini listeleyecek ve kahraman görselini içerecektir. İlk mağaza bölümü Giyim'e ayrılacak. İkinci mağaza bölümü Gear'ı içerecektir. Öğelerin her birinin ayrıntıları içeren ayrı bir Önizleme sayfası olacaktır. Zaten sepette bulunan ürünler, bunları kaldırma seçeneğine sahip olacaktır. Sepet seçilen tüm öğeleri listeleyecek ve toplamı hesaplayacaktır. OneEntry Projesi Oluşturun Öncelikle kullanıcının yeni bir hesaba kaydolması gerekecektir. Bunu yapmak için OneEntry ana sayfasına gidin ve e-posta hesabınızla . kaydolun Bundan sonra ve OneEntry kontrol paneline yönlendirileceksiniz. oturum açın Yeni bir proje oluşturarak başlayın. Bir ay boyunca Çalışma planını kullanmak için ücretsiz kod alacaksınız. Projenin oluşturulma sürecinde etkinleştirme şansınız olacak. Projenin oluşturulması birkaç dakika sürecektir. Hazır olduğunda proje durumu "Çalışıyor" olarak değişecek ve durum göstergesi yeşil olacaktır. Sayfaları Oluşturma Proje oluşturulduktan sonra, uygulama verilerini oluşturmak ve depolamak üzere CMS portalınıza erişmeniz için oturum açma ayrıntılarını içeren bir e-posta alacaksınız. Giriş yaptıktan sonra ilk sayfanızı oluşturabileceksiniz. İçerik Yönetimi'ne gidin, Yeni sayfa oluştur'a tıklayın ve gerekli tüm verileri (sayfa türleri, sayfa başlığı, sayfa ULR'si ve menü öğesinin adı) doldurun. Tüm veriler girildiğinde otomatik olarak kaydedilir. Ev, Giyim, Ekipman ve Sepet için 4 farklı sayfa oluşturun. Sayfalar oluşturulduktan sonra aşağıdaki ekran görüntüsündeki gibi görünmelidir. Nitelikler Oluştur Daha sonra saklayacağımız veri yapısını oluşturmamız gerekiyor. OneEntry CMS'de bu, verilere ilişkin niteliklerin oluşturulmasıyla gerçekleştirilir. Ayarlar'a gidin ve yatay menüden Nitelikler'i seçin. Ana sayfa için adı, işaretçiyi ve türü sağlayan bir özellik seti oluşturun: Oluşturulduktan sonra aşağıdaki ekran görüntüsündeki gibi görünecektir: Benzer şekilde Giyim ve Teçhizat için iki ayrı özellik seti oluşturalım. Oluşturulduktan sonra sonuç aşağıdaki ekran görüntüsündeki gibi görünmelidir. Şimdi her küme için belirli nitelikleri tanımlayalım. Daha önce Ana Sayfa bölümünde tel çerçeveye eklediğimiz içeriğe dayanarak başlığı, açıklamayı ve resmi görüntülemek istiyoruz. Ana Sayfa için dişli öğesine tıklayın ve aşağıdaki listede gösterildiği gibi aşağıdaki özellik adlarını, işaretçileri ve özellik türlerini oluşturun. Şimdi geri dönün ve Giyim için dişli simgesine tıklayın. Ürün başlığını, alt başlığını, açıklamasını, resmini ve fiyatını görüntülemek istediğimiz için bu sayfanın özellikleri biraz farklı olacaktır. Öznitelik yapısının nasıl görüneceği aşağıda açıklanmıştır: Daha sonra aynı yapıyı kullanacak olan Gear sayfası için de aynısını yapın: İçerik Ekle Projenin bu aşamasında içerik yapısını zaten tanımladık ve içeriğin kendisini oluşturmaya başlamaya hazırız. Daha önce site için tüm sayfalarınızı oluşturduğunuz İçerik Yönetimi bölümüne gidin: Ana Sayfa için düzenle düğmesine tıklayın. Bundan sonra Yatay menüdeki Nitelikler sekmesine tıklayın: Nitelikler kümesi için Ana Sayfa'yı seçin. Bu, daha önce Ana Sayfa Ayarlarında oluşturduğumuz tüm özellikleri yükleyecektir. Şimdi Ana sayfada görüntülenmesini istediğiniz bazı örnek verileri girin. Şimdi Giyim ve Teçhizat sayfalarımıza biraz içerik ekleyelim. Sayfa türünü Katalog olarak seçtiğimiz için soldaki menüden Katalog'u seçin; burada her iki sayfanın da görünmesi gerekir: Şimdi, Giyim için Ekle simgesine tıklayın ve birkaç öğe ekleyin. Öncelikle eklemek istediğiniz Ürünün Başlığını ekleyin. Şimdi Nitelikler sekmesine geçin, Nitelikler Grubu için Giyim'i seçin ve gerekli verileri doldurun. Katalog menüsüne geri dönün ve hem Giyim hem de Teçhizat için birkaç öğeye daha bakın. Demo uygulamamız için aşağıdaki ekran görüntüsünde gösterildiği gibi 4 öğe ekledim: API Erişim Jetonu Oluşturun OneEntry CMS'de oluşturulan tüm veriler korunmaktadır, dolayısıyla bunlara erişebilmek için özel bir belirteç oluşturmamız gerekecektir. Bunu yapmak için Ayarlar'a gidin ve Uygulama belirteçleri'ni seçin. Uygulama adını ve son kullanma tarihini girin ve Oluştur'a tıklayın. Bu benzersiz bir API anahtarı oluşturacaktır. Eylem listesindeki görünüm simgesini tıkladığınızda anahtarı görebileceksiniz. Öğreticinin bir sonraki bölümünde ihtiyacımız olacağı için panoya kopyalayın. NextJS Projesini Kurma Eğitimin bu bölümünde kodla çalışmaya başlayacağız ve NextJS projesini OneEntry CMS ile çalışacak şekilde yapılandıracağız. Terminali açın ve komutunu çalıştırın. npx create-next-app@latest CLI kurulum sihirbazını başlatacaktır. Projenizin adını girin ve aşağıda gösterildiği gibi tüm varsayılan değerleri seçin: Kurulumun tamamlanması için bir dakika verin; NextJS uygulaması oluşturulduğunda bir bildirim alacaksınız. Bundan sonra, komutunu kullanarak dizini yeni oluşturulan klasörle değiştirin ve ardından geliştirici sunucusunu başlatmak için komutunu çalıştırın. cd winter-sports npm run dev Erişmek için terminalde verilen bağlantıya tıklayın veya web tarayıcınızı açın ve manuel olarak adresine gidin. http://localhost:3000 NextJS geliştirici sunucusu açılış sayfası size sunulmalıdır: Şimdi uygulamamız için ihtiyaç duyacağımız çevresel değeri yaratalım. Kod düzenleyicinize geri dönün ve projenizin kökünde bir dosyası oluşturun. .env Daha önce panoya kopyaladığınız API anahtarını aşağıdaki gibi yapıştırın: API_KEY=your-api-code-from-oneentry Bu, OneEntry CMS'den veri almak için API çağrıları yaptığımızda, aracılığıyla anahtara erişmemize olanak tanıyacaktır. process.env.API_KEY Ayrıca NextJS'yi de yapılandırmamız gerekiyor, böylece medyayı harici bir etki alanından dahil etmemize olanak tanıyor. OneEntry CMS'deki görsellere erişmek için buna ihtiyacımız olacak. Proje kökünde dosyasını açın ve aşağıdaki şekilde düzenleyin: next.config.js const nextConfig = { images: { remotePatterns: [ { hostname: "ecommerce.oneentry.cloud", }, ], }, }; module.exports = nextConfig; Son olarak, tüm stilleri sıfırdan yazacağımız için uygulamanın Tailwind varsayılan stilini sıfırlamamız gerekecek. klasöründe bulunan dizininde dosyasını açın ve dosya içeriğini aşağıdaki şekilde değiştirin: src app globals.css @tailwind base; @tailwind components; @tailwind utilities; Türler Oluştur TypeScript ile çalışacağımız için uygulamamızda hangi veri türlerini kullanacağımızı tanımlamamız gerekecek. Bunu sayfaların ve bileşenlerin içinde yapabiliriz, ancak kodu daha temiz tutmak ve tekrarı önlemek için dizininde yeni bir arayüz oluşturun. Yeni oluşturulan klasörün içinde bir dosyası oluşturun ve kodu ekleyin: app interfaces 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; } Ürünler ve Sayfa verileri, hem ön uç oluşturma veri yapısına hem de getirme yöntemi aracılığıyla API'den gelen yanıta yönelik türlere sahip olacaktır. Ayrıca CMS'de URL parametrelerinden gelen veriler için veri türlerini, metin giriş alanlarından alınan veriler için ise Metin oluşturucuyu tanımladık. API Getirme İşlevleri Oluşturun Şimdi sayfalara ve ürünlere ilişkin verileri getirmek üzere OneEntry CMS ile iletişim kurmak için kullanacağımız bazı işlevleri oluşturalım. Yine, bunu her dosyada yapabiliriz, ancak kodu daha temiz tutmak için, dizini içinde içinde dosyası bulunan yeni bir klasörü oluşturalım: app fetchData.tsx services 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(); } işlevi, OneEntry CMS'de oluşturduğumuz tüm sayfalarla ilgili verileri getirecektir. getPages işlevi, parametresine dayalı olarak belirli bir ürün koleksiyonuna ilişkin verileri getirecektir. Fonksiyonu ürünler sayfasına aktardığımızda parametreyi geçeceğiz. getProducts category işlevi, açtığımız ürünün göre verileri getirecektir. Herhangi bir belirli ürünün önizleme sayfasına işlevi aktardığımızda parametreyi ileteceğiz. getProduct id OneEntry CMS erişimini doğrulamak amacıyla daha önce dosyasında tanımladığımız API anahtarına erişmek için kullandığımıza dikkat edin. .env process.env.API_KEY Yardımcı İşlevler Oluşturun Ayrıca, hâlâ klasöründeyken, içinde adında küçük yardımcı işlevler içeren yeni bir dosya oluşturalım: 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); } işlevi, sepete eklenen ürünlerin fiyatlarını toplayacak ve toplam değeri döndürecektir. calculateTotal önizleme rotasındaki bireysel öğelerin zaten sepete eklenip eklenmediğini tespit edecektir. boughtStatus sepete eklenen ürünler için dizideki ürünün konumunu tespit edecektir. cartIndex Bileşenler Oluşturma dizinine geri dönün ve içinde yeni bir klasör oluşturun. app components Yeni oluşturulan klasörü açın ve içine yedi ayrı dosya ekleyin: , , , , , , . Header.tsx Footer.tsx Text.tsx Card.tsx Preview.tsx Order.tsx AddToCart.tsx Başlık bileşeni dosyasını açın ve aşağıdaki kodu ekleyin: 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> ); } Başlık için şirket adını görüntüledik ve bileşen sayfalara aktarıldığında API'den alacağımız gezinme bağlantılarını döngüye aldık. İki sütunlu bir düzen oluşturduk ve tipik gezinme görünümünü elde etmek için her iki öğeyi de ekranın karşıt taraflarına yatay olarak yerleştirdik. Altbilgi bileşeni dosyasını açın ve aşağıdaki kodu ekleyin: 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> ); } Altbilgide şirkete ait örnek adı ve içerik haklarını cari yılla birlikte ekledik. İçeriği ortaladık ve biraz dolgu ekledik. Metin bileşeni dosyasını açın ve aşağıdaki kodu ekleyin: Text.tsx import { TextProps } from "../interfaces/data"; export default function Text({ className, text }: TextProps) { return ( <div className={className} dangerouslySetInnerHTML={{ __html: text }} /> ); } Metin bileşeni, OneEntry CMS'den aldığımız metin verilerini oluşturacak ve uygulamamızda HTML etiketleri olmadan düzgün bir şekilde görüntüleyecektir. Kart bileşeni dosyasını açın ve aşağıdaki kodu ekleyin: 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> ); } Kart bileşeninde her ürünün görselini, başlığını, alt başlığını ve fiyatını gösterdik. Sayfalara aktarıldıktan sonra tüm öğelerin haritasını çıkaracağız. Resim, kartın üst kısmında görüntülenecek, ardından başlık ve açıklama ve bileşenin sağ alt tarafında fiyat görüntülenecektir. Önizleme bileşeni dosyasını açın ve aşağıdaki kodu ekleyin: 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> ); } Önizleme bileşeni, kullanıcı tıkladığında her ürün hakkında daha fazla bilgi görüntülemek için kullanılacaktır. Ürün görselini, başlığını, fiyatını ve açıklamasını göstereceğiz. Düzen, sol sütunda resim ve sağda içeriğin geri kalanı görüntülenecek şekilde 2 sütuna bölünecektir. Sipariş bileşeni dosyasını açın ve aşağıdaki kodu ekleyin: 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> ); } Sipariş bileşeni, kullanıcının sepete eklediği tüm ürünleri listeleyecektir. Her öğe için resim, başlık, alt başlık ve fiyat görüntülenecektir. Bileşen oluşturulduktan sonra uygulama, o anda sepette bulunan tüm öğelere erişecek, bunları durum değişkenine ayarlayacak ve bunları yöntemi aracılığıyla ekrana aktaracaktır. cardItems map Oluşturulan öğelerin toplam miktarı, dosyasından içe aktardığımız işlevi aracılığıyla hesaplanacaktır. helpers.tsx calculateTotal AddToCart bileşeni dosyasını açın ve aşağıdaki kodu ekleyin: 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> ); } addToCart bileşeni, bireysel ürün önizleme sayfasında görüntülenecek ve kullanıcının ürünü alışveriş sepetine eklemesine olanak tanıyacaktır. Oluşturma sonrasında işlevi, ürünün daha önce sepete eklenip eklenmediğini tespit edecektir. Oluşturulan düğme değilse "Sepete ekle" görüntülenir, aksi takdirde "Sepete kaldır" yazacaktır. isPurchased işlevi tıklama özelliği, yukarıdaki duruma göre ürünü öğeler dizisine ekleyecek veya bu diziden kaldıracaktır. handleButtonClick Sayfa Oluştur Son olarak öğreticinin önceki bölümünde oluşturduğumuz bileşenleri içe aktaralım ve uygulamanın sayfa mantığını oluşturalım. Ana sayfa dizininde dosyasını açın ve içeriğini aşağıdaki gibi düzenleyin: app page.tsx 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> ); } Ana sayfada, Başlığa ilişkin verileri almak için ilk önce işlevini çağıracağız. getPages Daha sonra Hero sayfası verilerini getirmek için işlevini kullanırız ve ardından bunları daha kolay işlenmesi için nesnesine dönüştürürüz. getValues pageContent Daha sonra içe aktarılan Üstbilgi ve Altbilgi bileşenlerini oluşturuyoruz ve ayrıca Kahraman başlığı, açıklaması ve görseli için gerekli değerleri iletiyoruz. Ürünler sayfası dizininde ve içinde yeni bir klasör oluşturun - dosyası. app [category] page.tsx Belirli dosya adlarının kullanılması önemlidir çünkü NextJS, rotaları yönetmek ve URL parametrelerine erişmek için bu adı kullanır. Aşağıdaki kodu dosyasına ekleyin: 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> ); } Ürünler sayfası için, sitenin hangi sayfasının ziyaret edildiğine bağlı olarak hangi ürün kategorisini getirmemiz gerektiğini açıklamak için önce URL'den parametresini alırız ve bunu ayrıca işlevine aktarırız. category getProducts Veriler alındıktan sonra, daha kolay işlenmesi için sayfanın gerekli tüm niteliklerini içeren bir ürün dizisi yaratırız. productItems Daha sonra metodu ile döngü yapıp, klasöründen içe aktardığımız Card bileşenine props'ı geçirerek ekrana aktarıyoruz. map component Önizleme sayfası klasörünün içinde adında başka bir klasör oluşturun. [category] [productId] Yeni oluşturulan klasörü açın ve içinde aşağıdaki kodu içeren bir dosyası oluşturun: 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> ); } Bu sayfa, kullanıcıların ürünler sayfasındaki kartlarına tıkladıklarında herhangi bir ürün için daha fazla ayrıntı görmesine olanak tanıyacaktır. Önizleme sayfasında hangi ürünün görüntülendiğine bağlı olarak hangi ürünü getirmemiz gerektiğini belirtmek için önce URL'den parametresini alırız ve bunu daha sonra işlevine aktarırız. productId getProduct Veriler alındıktan sonra, Önizleme bileşenine destek olarak aktarılacak tüm gerekli özniteliklerden oluşan bir ürün yaratırız. productItem Ayrıca parametresini de alıyoruz, çünkü bunu Sepete Ekle bileşenine aktarmamız gerekiyor, böylece Sepet sayfasındaki ürün için geçerli bir bağlantı oluşturabiliriz. category Sepet sayfası Son olarak dizininde yeni bir klasör oluşturun. app cart Açın, içinde aşağıdaki kodla yeni bir dosyası oluşturun: 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> ); } Önce gerekli verileri getirdik ve ardından bunları sahne donanımı olarak Başlığa aktardık. Daha sonra navigasyonlu Başlık bileşenini, kullanıcının sepete eklediği tüm ürünleri listeleyecek Sipariş bileşenini ve ayrıca şirket adının ve telif hakkı bilgilerinin yer aldığı Altbilgi bileşenini render ettik. Test yapmak Tebrikler, çalışan bir proje yaptınız! Öncelikle geliştirici sunucusunun hala çalışıp çalışmadığını kontrol edin. Değilse, yeniden başlatmak için komutunu çalıştırın ve görüntülemek için erişin. npm run dev localhost:3000'e Projeniz artık şöyle görünmeli: Görüldüğü gibi veri alanlarında belirttiğimiz Home öznitelik setinden Home bölümü içeriği başarıyla getirildi. Ayrıca OneEntry CMS kataloğundaki tüm öğeler, tüm bilgiler doğru şekilde aktarılarak Giyim ve Teçhizat bölümlerine getirildi. Kullanıcılar ayrıca NextJS rota işleme ve ürün parametreleri sayesinde her ürünü kendi özel sayfasında ayrı ayrı önizleyebilir. Ayrıca, tüm işlevler ve olaylar beklendiği gibi çalışır ve kullanıcı, toplam hesaplanarak alışveriş sepetine ürün ekleyip çıkarabilir. Çözüm Bu eğitimde, sayesinde kullanıcıların web sitesi sayfalarını ve içeriklerini oluşturmasına, güncellemesine ve silmesine ve ayrıca ürünleri kullanımı kolay bir katalog arayüzü ile kolayca yönetmesine olanak tanıyan bir e-Ticaret projesi oluşturduk. OneEntry CMS Kod mevcuttur, bu nedenle onu kopyalamaktan ve ihtiyaçlarınıza uyacak şekilde daha fazla işlevsellik eklemekten çekinmeyin. Daha fazla menü bölümü ekleyebilir, tek tek bileşenleri genişletebilir ve hatta yeni özellikleri uygulamak için daha fazla bileşen ekleyebilirsiniz. GitHub'da Umarız bu sizin için yararlı olur ve OneEntry CMS'yi arka uç çözümü olarak nasıl kullanacağınız, uygulamanızın ön ucuyla nasıl eşleştireceğiniz ve NextJS, Typescript ve Tailwind'in en iyi özelliklerini nasıl kullanacağınız konusunda fikir sahibi olursunuz. . abone olarak keşfettiğim en iyi kaynakları, araçları, üretkenlik ipuçlarını ve kariyer geliştirme ipuçlarını aldığınızdan emin olun! Bültenime Ayrıca benimle , ve üzerinden bağlantı kurun! Twitter LinkedIn GitHub da yayınlandı Burada