次.ストラピとチャクラUIとのJS電子商取引アプリ
この記事では、我々は我々が前にした私たちの管理パネルの電子商取引アプリを作成します.
これは、現在3のバージョンを絞り込みでヘッド無しで使用されます.あなたはヘッドレス機能を使用して任意のUIライブラリを使用することができます.
私たちはStrapi and Chakra-UI 一緒に電子商取引クライアントの例のアプリケーションで.
プロジェクトセットアップの改善
私たちの洗練されたプロジェクトを作成することから始めましょう.あなたはsuperplate リファインプロジェクトを作成するには
npx superplate-cli -p refine-nextjs refine-ecommerce-example
✔ What will be the name of your app · refine-ecommerce-example
✔ Package manager: · npm
✔ Do you want to using UI Framework? > No(headless)
✔ Data Provider: Strapi
✔ i18n - Internationalization: · no
SuperPlateはすぐに我々が選択した機能に応じて我々の洗練されたプロジェクトを作成します.あとで使用するChackra UIパッケージをインストールし続けましょう.インストール
cd refine-ecommerce-example
npm i @pankod/refine-strapi-v4
npm i @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^6
我々の洗練されたプロジェクトとインストールは、現在準備ができています!使い始めましょう.用途
Strapi - V 4用のリファインの設定
pages/index.tsx:
import React from "react";
import { AppProps } from "next/app";
import Head from "next/head";
import { Refine } from "@pankod/refine-core";
import routerProvider from "@pankod/refine-nextjs-router";
import { DataProvider } from "@pankod/refine-strapi-v4";
const API_URL = "https://api.strapi-multi-tenant.refine.dev/api";
function MyApp({ Component, pageProps }: AppProps): JSX.Element {
const dataProvider = DataProvider(API_URL);
return (
<Refine
routerProvider={routerProvider}
dataProvider={dataProvider}
>
<Component {...pageProps} />
</Refine>
);
}
チャクラのUIプロバイダのセットアップ
pages/index.tsx:
import React from "react";
import { AppProps } from "next/app";
import Head from "next/head";
import { Refine } from "@pankod/refine-core";
import routerProvider from "@pankod/refine-nextjs-router";
import { DataProvider } from "@pankod/refine-strapi-v4";
import { ChakraProvider } from "@chakra-ui/react";
const API_URL = "https://api.strapi-multi-tenant.refine.dev/api";
function MyApp({ Component, pageProps }: AppProps): JSX.Element {
const dataProvider = DataProvider(API_URL);
return (
<Refine routerProvider={routerProvider} dataProvider={dataProvider}>
<ChakraProvider>
<Component {...pageProps} />
</ChakraProvider>
</Refine>
);
}
コレクションの作成
私たちはstrapi
store
, product
and order
との間の関係を追加しました.コレクションを作成する方法の詳細については、チェックすることができますhere .我々は以前のstrapiの多国間ガイドで私達のコレクションを作成しました.現在、同じコレクションを使用します.
Refer to the Project Collections for detailed information. →
レイアウトの作成
リファインヘッドレスは、任意のUIと提携していません.それは完全にあなたのUIをカスタマイズすることです.この例の簡単なレイアウトを作りましょう.
我々が今作成したレイアウトは、洗練されたロゴだけを示します.次の手順でレイアウトを編集します.
components/Layout.tsx:
import { Box, Container, Flex, Image } from "@chakra-ui/react";
export const Layout: React.FC = ({ children }) => {
return (
<Box
display={"flex"}
flexDirection={"column"}
backgroundColor={"#eeeeee"}
minH={"100vh"}
>
<Container maxW={"container.lg"}>
<Flex justify={"space-between"} mt={4} alignSelf={"center"}>
<a href="https://refine.dev">
<Image alt="Refine Logo" src={"./refine_logo.png"} />
</a>
</Flex>
{children}
</Container>
</Box>
);
};
pages/_app.tsx:
import React from "react";
import { AppProps } from "next/app";
import Head from "next/head";
import { Refine } from "@pankod/refine-core";
import routerProvider from "@pankod/refine-nextjs-router";
import { DataProvider } from "@pankod/refine-strapi-v4";
import { ChakraProvider } from "@chakra-ui/react";
import { Layout } from "src/components";
const API_URL = "https://api.strapi-multi-tenant.refine.dev/api";
function MyApp({ Component, pageProps }: AppProps): JSX.Element {
const dataProvider = DataProvider(API_URL);
return (
<Refine
routerProvider={routerProvider}
dataProvider={dataProvider}
Layout={Layout}
>
<ChakraProvider>
<Component {...pageProps} />
</ChakraProvider>
</Refine>
);
}
プロダクトカードデザイン
チャクラのUIを使用して製品カードを設計しましょう.
src/components/ProductCard.tsx
import React from "react";
import { Box, Image, Badge, Button } from "@chakra-ui/react";
export type ProductProps = {
id: string;
title: string;
description: string;
cardImage: string;
};
export const ProductCard: React.FC<ProductProps> = ({
id,
title,
description,
cardImage,
}) => {
return (
<Box maxH={"sm"} borderWidth="1px" borderRadius="lg" overflow="hidden">
<Image w={"100%"} h={200} src={cardImage} />
<Box p="6" bgColor={"gray.600"}>
<Box display="flex" alignItems="baseline" mb={2} ml={-2}>
<Badge borderRadius="full" px="2" colorScheme="teal">
New Product
</Badge>
</Box>
<Box
mt="1"
fontWeight="semibold"
as="h4"
lineHeight="tight"
isTruncated
color={"white"}
>
{title}
</Box>
<Box color={"white"}>{}</Box>
<Box
color="white"
fontSize="sm"
display={"flex"}
mt={4}
justifyContent={"flex-end"}
></Box>
</Box>
</Box>
);
};
弊社製品カードコンポーネントを作成しました.さあ、私たちの製品をレピから取り出して見せてみましょう.
製品をSSRでフェッチする
最初に、我々の製品をNextjs
getServerSideProps
関数.GetServerSideProps
pages/index.tsx:
import { GetServerSideProps } from "next";
import { DataProvider } from "@pankod/refine-strapi-v4";
import { IProduct } from "interfaces";
const API_URL = "https://api.strapi-multi-tenant.refine.dev/api";
export const getServerSideProps: GetServerSideProps = async (context) => {
const data = await DataProvider(API_URL).getList<IProduct>({
resource: "products",
metaData: { populate: ["image"] },
});
return {
props: { products: data },
};
};
製品リストの作成
上記のデータをリファインの
useTable
フック.では、PropertCardコンポーネントにデータを入れましょう.pages/index.tsx:
import { GetServerSideProps } from "next";
import { LayoutWrapper, GetListResponse, useTable } from "@pankod/refine-core";
import { DataProvider } from "@pankod/refine-strapi-v4";
import { IProduct } from "interfaces";
import { SimpleGrid } from "@chakra-ui/react";
import { ProductCard } from "src/components";
const API_URL = "https://api.strapi-multi-tenant.refine.dev/api";
type ItemProps = {
products: GetListResponse<IProduct>;
};
export const ProductList: React.FC<ItemProps> = ({ products }) => {
const { tableQueryResult } = useTable<IProduct>({
resource: "products",
queryOptions: {
initialData: products,
},
metaData: { populate: ["image"] },
});
return (
<LayoutWrapper>
<SimpleGrid columns={[1, 2, 3]} mt={6} spacing={3}>
{tableQueryResult.data?.data.map((item) => (
<ProductCard
id={item.id}
title={item.title}
description={item.description}
cardImage={
item.image
? API_URL + item.image.url
: "./error.png"
}
/>
))}
</SimpleGrid>
</LayoutWrapper>
);
};
export default ProductList;
export const getServerSideProps: GetServerSideProps = async (context) => {
const data = await DataProvider(API_URL).getList<IProduct>({
resource: "products",
metaData: { populate: ["image"] },
});
return {
props: { products: data },
};
};
ストアベースのフィルタリングの追加
我々は上記のすべての製品を取得している.さて、ストアを取得し、ストア固有の製品を個別に一覧表示しましょう.
まず、リファインを使って店に行きましょう
useMany
フックの内側getServerSideProps
関数.次に、ストアのボタンを作成します.これらのボタンをクリックすると、ストアが選択され、我々はフィルタリングを行いますuseTable
setFilters
とそのストアに固有の製品を一覧表示します.pages/index.tsx:
export const getServerSideProps: GetServerSideProps = async (context) => {
const data = await DataProvider(API_URL).getList<IProduct>({
resource: "products",
metaData: { populate: ["image"] },
pagination: { current: 1, pageSize: 9 },
});
const { data: storesData } = await DataProvider(API_URL).getMany({
resource: "stores",
ids: ["1", "2", "3"],
});
return {
props: {
products: data,
stores: storesData,
},
};
};
pages/index.tsx:
import { GetServerSideProps } from "next";
import { LayoutWrapper, GetListResponse, useTable } from "@pankod/refine-core";
import { DataProvider } from "@pankod/refine-strapi-v4";
import { IProduct, IStore } from "interfaces";
import { Button, SimpleGrid, Flex, Text } from "@chakra-ui/react";
import { ProductCard, FilterButton } from "src/components";
const API_URL = "https://api.strapi-multi-tenant.refine.dev/api";
type ItemProps = {
products: GetListResponse<IProduct>;
stores: IStore[];
};
export const ProductList: React.FC<ItemProps> = ({ products, stores }) => {
const { tableQueryResult, setFilters } = useTable<IProduct>({
resource: "products",
queryOptions: {
initialData: products,
},
metaData: { populate: ["image"] },
});
return (
<LayoutWrapper>
<Flex mt={6} gap={2}>
<FilterButton
setFilters={() =>
setFilters([
{
field: "stores][id]",
operator: "eq",
value: undefined,
},
])
}
>
<Text fontSize={{ base: "12px", md: "14px", lg: "14px" }}>
All Products
</Text>
</FilterButton>
{stores?.map((item) => {
return (
<FilterButton
setFilters={() =>
setFilters([
{
field: "stores][id]",
operator: "eq",
value: item.id,
},
])
}
>
<Text
fontSize={{
base: "12px",
md: "14px",
lg: "14px",
}}
>
{item.title}
</Text>
</FilterButton>
);
})}
</Flex>
<SimpleGrid columns={[1, 2, 3]} mt={6} spacing={3}>
{tableQueryResult.data?.data.map((item) => (
<ProductCard
id={item.id}
title={item.title}
description={item.description}
cardImage={
item.image
? API_URL + item.image.url
: "./error.png"
}
/>
))}
</SimpleGrid>
</LayoutWrapper>
);
};
export default ProductList;
export const getServerSideProps: GetServerSideProps = async (context) => {
const data = await DataProvider(API_URL).getList<IProduct>({
resource: "products",
metaData: { populate: ["image"] },
pagination: { current: 1, pageSize: 9 },
});
const { data: storesData } = await DataProvider(API_URL).getMany({
resource: "stores",
ids: ["1", "2", "3"],
});
return {
props: {
products: data,
stores: storesData,
},
};
};
ページの追加
我々はすべての製品を一覧表示します
All Products
ページ.ページにページを追加し、ページに製品を分割しましょう.を使ってページネーションを行いますpageSize
, current
USETableフックからのSetcurrentプロパティ.Refer to the useTable documentation for detailed information. →
pages/index.tsx:
import { GetServerSideProps } from "next";
import { LayoutWrapper, GetListResponse, useTable } from "@pankod/refine-core";
import { DataProvider } from "@pankod/refine-strapi-v4";
import { IProduct, IStore } from "interfaces";
import { Button, SimpleGrid, Flex, Text } from "@chakra-ui/react";
import { ProductCard, FilterButton } from "src/components";
const API_URL = "https://api.strapi-multi-tenant.refine.dev/api";
type ItemProps = {
products: GetListResponse<IProduct>;
stores: IStore[];
};
export const ProductList: React.FC<ItemProps> = ({ products, stores }) => {
const { tableQueryResult, setFilters, current, setCurrent, pageSize } =
useTable<IProduct>({
resource: "products",
queryOptions: {
initialData: products,
},
initialPageSize: 9,
metaData: { populate: ["image"] },
});
const totalPageCount = Math.ceil(tableQueryResult.data?.total!! / pageSize);
return (
<LayoutWrapper>
<Flex mt={6} gap={2}>
<FilterButton
setFilters={() =>
setFilters([
{
field: "stores][id]",
operator: "eq",
value: undefined,
},
])
}
>
<Text fontSize={{ base: "12px", md: "14px", lg: "14px" }}>
All Products
</Text>
</FilterButton>
{stores?.map((item) => {
return (
<FilterButton
setFilters={() =>
setFilters([
{
field: "stores][id]",
operator: "eq",
value: item.id,
},
])
}
>
<Text
fontSize={{
base: "12px",
md: "14px",
lg: "14px",
}}
>
{item.title}
</Text>
</FilterButton>
);
})}
</Flex>
<SimpleGrid columns={[1, 2, 3]} mt={6} spacing={3}>
{tableQueryResult.data?.data.map((item) => (
<ProductCard
id={item.id}
title={item.title}
description={item.description}
cardImage={
item.image
? API_URL + item.image.url
: "./error.png"
}
/>
))}
</SimpleGrid>
<Flex justify={"flex-end"} mt={4} mb={4} gap={2}>
{Array.from(Array(totalPageCount), (e, i) => {
if (current > totalPageCount) {
setCurrent(i);
}
return (
<Button
colorScheme={"teal"}
onClick={() => setCurrent(i + 1)}
>
{"Page: " + (i + 1)}
</Button>
);
})}
</Flex>
</LayoutWrapper>
);
};
export default ProductList;
export const getServerSideProps: GetServerSideProps = async (context) => {
const data = await DataProvider(API_URL).getList<IProduct>({
resource: "products",
metaData: { populate: ["image"] },
pagination: { current: 1, pageSize: 9 },
});
const { data: storesData } = await DataProvider(API_URL).getMany({
resource: "stores",
ids: ["1", "2", "3"],
});
return {
props: { products: data, stores: storesData },
};
};
バスケットとお支払い機能を追加する
電子商取引アプリケーションでなければならないステップの1つはカートと支払い取引です.この例では、Snipcart このプロセスのために.
Refer to the Snipcart documentation for detailed information. →
ウィジェットのインストール
pages/_app.tsx:
function MyApp({ Component, pageProps }: AppProps): JSX.Element {
const dataProvider = DataProvider(API_URL);
return (
<>
<Head>
<link rel="preconnect" href="https://app.snipcart.com" />
<link
rel="stylesheet"
href="https://cdn.snipcart.com/themes/v3.0.16/default/snipcart.css"
/>
<script
async
src="https://cdn.snipcart.com/themes/v3.0.16/default/snipcart.js"
/>
</Head>
<Refine
routerProvider={routerProvider}
dataProvider={dataProvider}
resources={[{ name: "products" }]}
Layout={Layout}
>
<ChakraProvider>
<Component {...pageProps} />
</ChakraProvider>
</Refine>
<div hidden id="snipcart" data-api-key="YOUR_SNIPCART_TEST_KEY" />
</>
);
}
ProductCardコンポーネントの「バスケットに追加」ボタンの追加
src/components/ProductCard.tsx:
import React from "react";
import { Box, Image, Badge, Button } from "@chakra-ui/react";
export type ProductProps = {
id: string;
title: string;
description: string;
cardImage: string;
};
export const ProductCard: React.FC<ProductProps> = ({
id,
title,
description,
cardImage,
}) => {
return (
<Box
maxH={"sm"}
maxW="sm"
borderWidth="1px"
borderRadius="lg"
overflow="hidden"
>
<Image w={"100%"} h={200} src={cardImage} />
<Box p="6" bgColor={"gray.600"}>
<Box display="flex" alignItems="baseline" mb={2} ml={-2}>
<Badge borderRadius="full" px="2" colorScheme="teal">
New Product
</Badge>
</Box>
<Box
mt="1"
fontWeight="semibold"
as="h4"
lineHeight="tight"
isTruncated
color={"white"}
>
{title}
</Box>
<Box
color="white"
fontSize="sm"
display={"flex"}
mt={4}
justifyContent={"flex-end"}
>
<Button
className="buy-button snipcart-add-item"
bgColor={"green.400"}
data-item-id={id}
data-item-price="5"
data-item-url="/"
data-item-name={title}
data-item-description={description}
data-item-image={cardImage}
>
Add to Basket
</Button>
</Box>
</Box>
</Box>
);
};
結論
つのフレームワークから他のフレームワークを区別する最大の機能の一つは、それがカスタマイズ可能です.洗練されたヘッドレスと組み合わせると、今より多くのカスタマイズオプションを提供します.これはあなたが開発するプロジェクトの利便性を大いに提供します.
この記事でご覧のように、クライアントの一部を開発しましたAdmin Panel , 私たちは前にした、洗練された.リファインは、B 2 BとB 2 Cアプリケーションを任意の制限なしに開発し、完全にカスタマイズ可能な方法で機会を提供しています.
Refer to the Admin side of the project →
Source Code
Live CodeSandbox Example
Check out for detailed information about refine. →
Reference
この問題について(次.ストラピとチャクラUIとのJS電子商取引アプリ), 我々は、より多くの情報をここで見つけました https://dev.to/pankod/nextjs-e-commerce-app-with-strapi-and-chakra-ui-1cf5テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol