From fed42bac87b1e599db4ca390c25bdf531b9da2d1 Mon Sep 17 00:00:00 2001 From: lytrankieio123 Date: Thu, 7 Oct 2021 14:09:23 +0700 Subject: [PATCH] :sparkles: feat:(product detail) get relevant product :%s --- framework/commerce/types/product.ts | 4 +- .../vendure/api/operations/get-product.ts | 17 +++----- framework/vendure/schema.d.ts | 12 ++++++ .../utils/queries/get-product-query.ts | 3 ++ pages/product/[slug].tsx | 41 +++++++++++++++---- .../ReleventProducts/ReleventProducts.tsx | 10 +++-- src/utils/constanst.utils.ts | 1 + 7 files changed, 66 insertions(+), 22 deletions(-) diff --git a/framework/commerce/types/product.ts b/framework/commerce/types/product.ts index e1a8da200..e02113814 100644 --- a/framework/commerce/types/product.ts +++ b/framework/commerce/types/product.ts @@ -43,8 +43,10 @@ export type Product = { slug?: string path?: string images: ProductImage[] - price: ProductPrice + price: number + currencyCode: CurrencyCode options: ProductOption[] + facetValueIds?: string[] } export type ProductCard = { diff --git a/framework/vendure/api/operations/get-product.ts b/framework/vendure/api/operations/get-product.ts index 4ab9ed2d9..239eb5b61 100644 --- a/framework/vendure/api/operations/get-product.ts +++ b/framework/vendure/api/operations/get-product.ts @@ -16,10 +16,8 @@ export default function getProductOperation({ variables: { slug: string } config?: Partial preview?: boolean - }): Promise { + }): Promise { const config = commerce.getConfig(cfg) - - const locale = config.locale const { data } = await config.fetch(query, { variables }) const product = data.product @@ -28,7 +26,6 @@ export default function getProductOperation({ return product.optionGroups.find((og) => og.id === id)!.name } return { - product: { id: product.id, name: product.name, description: product.description, @@ -49,20 +46,18 @@ export default function getProductOperation({ values: [{ label: o.name }], })), })), - price: { - value: product.variants[0].priceWithTax / 100, - currencyCode: product.variants[0].currencyCode, - }, + price: product.variants[0].priceWithTax / 100, + currencyCode: product.variants[0].currencyCode, options: product.optionGroups.map((og) => ({ id: og.id, displayName: og.name, values: og.options.map((o) => ({ label: o.name })), })), - } as Product, - } + facetValueIds: product.facetValues.map(item=> item.id) + } as Product } - return {} + return null } return getProduct diff --git a/framework/vendure/schema.d.ts b/framework/vendure/schema.d.ts index 8f49e2d2d..d83b0276a 100644 --- a/framework/vendure/schema.d.ts +++ b/framework/vendure/schema.d.ts @@ -3338,6 +3338,18 @@ export type GetProductQuery = { __typename?: 'Query' } & { > } > + facetValues: Array< + { __typename?: 'FacetValue' } & Pick< + FacetValue, + 'id' + > + > + collections: Array< + { __typename?: 'Collection' } & Pick< + Collection, + 'id' + > + > } > } diff --git a/framework/vendure/utils/queries/get-product-query.ts b/framework/vendure/utils/queries/get-product-query.ts index b2c502da9..f9d4e7002 100644 --- a/framework/vendure/utils/queries/get-product-query.ts +++ b/framework/vendure/utils/queries/get-product-query.ts @@ -36,6 +36,9 @@ export const getProductQuery = /* GraphQL */ ` name } } + facetValues { + id + } } } ` diff --git a/pages/product/[slug].tsx b/pages/product/[slug].tsx index fa307d1c2..f3e31a655 100644 --- a/pages/product/[slug].tsx +++ b/pages/product/[slug].tsx @@ -1,21 +1,21 @@ +import { Product } from '@framework/schema' import commerce from '@lib/api/commerce' import { GetStaticPathsContext, GetStaticPropsContext, InferGetStaticPropsType } from 'next' import { Layout, RecipeDetail, RecommendedRecipes, RelevantBlogPosts } from 'src/components/common' import { ProductInfoDetail, ReleventProducts, ViewedProducts } from 'src/components/modules/product-detail' -import { REVALIDATE_TIME } from 'src/utils/constanst.utils' +import { MAX_PRODUCT_CAROUSEL, REVALIDATE_TIME } from 'src/utils/constanst.utils' import { BLOGS_DATA_TEST, INGREDIENT_DATA_TEST, RECIPE_DATA_TEST } from 'src/utils/demo-data' import { getAllPromies } from 'src/utils/funtion.utils' import { PromiseWithKey } from 'src/utils/types.utils' -export default function Slug({ product }: InferGetStaticPropsType) { - console.log("product: ", product) +export default function Slug({ product, relevantProducts }: InferGetStaticPropsType) { return <> - + @@ -31,12 +31,34 @@ export async function getStaticProps({ let promisesWithKey = [] as PromiseWithKey[] let props = {} as any - const productPromise = commerce.getProduct({ + const product = await commerce.getProduct({ variables: { slug: params!.slug }, config, preview, }) - promisesWithKey.push({ key: 'product', promise: productPromise, keyResult: 'product' }) + props.product = product + + + if (!product) { + throw new Error(`Product with slug '${params!.slug}' not found`) + } + + // relevant product + const relevantFacetIds = product.facetValueIds + if (relevantFacetIds && relevantFacetIds.length > 0) { + const relevantProductsPromise = commerce.getAllProducts({ + variables: { + first: MAX_PRODUCT_CAROUSEL, + facetValueIds: relevantFacetIds, + }, + config, + preview, + }) + promisesWithKey.push({ key: 'relevantProducts', promise: relevantProductsPromise, keyResult: 'products' }) + } else { + props.relevantProducts = [] + } + try { const promises = getAllPromies(promisesWithKey) @@ -47,12 +69,17 @@ export async function getStaticProps({ return null }) + if (props.relevantProducts.length > 0) { + const relevantProducts = props.relevantProducts.filter((item: Product) => item.id !== product.id) + props.relevantProducts = relevantProducts + } + return { props, revalidate: REVALIDATE_TIME, } } catch (err) { - + console.log('err: ', err) } } diff --git a/src/components/modules/product-detail/ReleventProducts/ReleventProducts.tsx b/src/components/modules/product-detail/ReleventProducts/ReleventProducts.tsx index e11d31065..d6480beb4 100644 --- a/src/components/modules/product-detail/ReleventProducts/ReleventProducts.tsx +++ b/src/components/modules/product-detail/ReleventProducts/ReleventProducts.tsx @@ -1,13 +1,17 @@ +import { ProductCard } from '@commerce/types/product'; import React from 'react'; import ListProductWithInfo from 'src/components/common/ListProductWithInfo/ListProductWithInfo'; -import { PRODUCT_DATA_TEST } from 'src/utils/demo-data'; -const ReleventProducts = () => { +interface Props { + data: ProductCard[] +} + +const ReleventProducts = ({ data }: Props) => { return ( ); }; diff --git a/src/utils/constanst.utils.ts b/src/utils/constanst.utils.ts index 6736e77c0..7d0cf9ba5 100644 --- a/src/utils/constanst.utils.ts +++ b/src/utils/constanst.utils.ts @@ -1,6 +1,7 @@ import DefaultImg from '../../public/assets/images/default_img.jpg' export const REVALIDATE_TIME = 60 +export const MAX_PRODUCT_CAROUSEL = 20 export const BLUR_DATA_IMG = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mN8fBIAApUBruKYvzsAAAAASUVORK5CYII=' export const DEFAULT_IMG = DefaultImg