feat: get-product-detail

This commit is contained in:
Tan Le
2021-10-07 16:16:24 +07:00
parent 51d1624fab
commit 148326c7ef
9 changed files with 40 additions and 107 deletions

View File

@@ -47,6 +47,8 @@ export type Product = {
currencyCode: CurrencyCode currencyCode: CurrencyCode
options: ProductOption[] options: ProductOption[]
facetValueIds?: string[] facetValueIds?: string[]
collectionIds?: string[]
collection?: string,
} }
export type ProductCard = { export type ProductCard = {

View File

@@ -53,7 +53,8 @@ export default function getProductOperation({
displayName: og.name, displayName: og.name,
values: og.options.map((o) => ({ label: o.name })), values: og.options.map((o) => ({ label: o.name })),
})), })),
facetValueIds: product.facetValues.map(item=> item.id) facetValueIds: product.facetValues.map(item=> item.id),
collectionIds: product.collections.map(item => item.id)
} as Product } as Product
} }

View File

@@ -39,6 +39,9 @@ export const getProductQuery = /* GraphQL */ `
facetValues { facetValues {
id id
} }
collections {
id
}
} }
} }
` `

View File

@@ -12,7 +12,7 @@ import { PromiseWithKey } from 'src/utils/types.utils'
export default function Slug({ product, relevantProducts, collections }: InferGetStaticPropsType<typeof getStaticProps>) { export default function Slug({ product, relevantProducts, collections }: InferGetStaticPropsType<typeof getStaticProps>) {
return <> return <>
<ProductInfoDetail /> <ProductInfoDetail productDetail={product} collections={collections}/>
<RecipeDetail ingredients={INGREDIENT_DATA_TEST} /> <RecipeDetail ingredients={INGREDIENT_DATA_TEST} />
<RecommendedRecipes data={RECIPE_DATA_TEST} /> <RecommendedRecipes data={RECIPE_DATA_TEST} />
<ReleventProducts data={relevantProducts} collections={collections}/> <ReleventProducts data={relevantProducts} collections={collections}/>

View File

@@ -1,83 +1,28 @@
import React from 'react' import React, { useMemo } from 'react';
import ProductImgs from './components/ProductImgs/ProductImgs' import ProductImgs from './components/ProductImgs/ProductImgs'
import ProductInfo from './components/ProductInfo/ProductInfo' import ProductInfo from './components/ProductInfo/ProductInfo'
import s from './ProductInfoDetail.module.scss' import s from './ProductInfoDetail.module.scss'
import { GetStaticPropsContext, GetStaticPathsContext, InferGetStaticPropsType } from 'next' import { Product } from '@commerce/types/product'
import commerce from '@lib/api/commerce' import { Collection } from '@framework/schema'
import { PromiseWithKey } from 'src/utils/types.utils' import { getCategoryNameFromCollectionId } from 'src/utils/funtion.utils';
import { getAllPromies } from 'src/utils/funtion.utils'
import { ProductCard } from '@commerce/types/product';
import { useRouter } from 'next/router'
interface Props { interface Props {
productDetail: ProductCard[], productDetail: Product,
collections: Collection[]
} }
const ProductInfoDetail = ({ product }: InferGetStaticPropsType<typeof getStaticProps>) => { const ProductInfoDetail = ({ productDetail, collections }: Props) => {
console.log(product) const dataWithCategoryName = useMemo(() => {
return {
...productDetail,
collection: getCategoryNameFromCollectionId(collections, productDetail.collectionIds ? productDetail.collectionIds[0] : undefined)
}
}, [productDetail, collections])
return ( return (
<section className={s.productInfoDetail}> <section className={s.productInfoDetail}>
<ProductImgs/> <ProductImgs productImage={productDetail.images}/>
<ProductInfo/> <ProductInfo productInfoDetail={dataWithCategoryName}/>
</section > </section >
) )
} }
export async function getStaticProps({
params,
locale,
locales,
preview,
}: GetStaticPropsContext<{ slug: string }>) {
const config = { locale, locales }
const pagesPromise = commerce.getAllPages({ config, preview })
const siteInfoPromise = commerce.getSiteInfo({ config, preview })
const productPromise = commerce.getProduct({
variables: { slug: params!.slug },
config,
preview,
})
// const allProductsPromise = commerce.getAllProducts({
// variables: { first: 4 },
// config,
// preview,
// })
const { pages } = await pagesPromise
const { categories } = await siteInfoPromise
const { product } = await productPromise
// const { products: relatedProducts } = await allProductsPromise
if (!product) {
throw new Error(`Product with slug '${params!.slug}' not found`)
}
return {
props: {
pages,
product,
// relatedProducts,
categories,
},
revalidate: 200,
}
}
// export async function getStaticPaths({ locales }: GetStaticPathsContext) {
// const { products } = await commerce.getAllProductPaths()
// return {
// paths: locales
// ? locales.reduce<string[]>((arr, locale) => {
// // Add a product path for every locale
// products.forEach((product: any) => {
// arr.push(`/${locale}/product${product.path}`)
// })
// return arr
// }, [])
// : products.map((product: any) => `/product${product.path}`),
// fallback: 'blocking',
// }
// }
export default ProductInfoDetail export default ProductInfoDetail

View File

@@ -3,15 +3,15 @@ import { ImgWithLink } from 'src/components/common'
import s from './ProductImgItem.module.scss' import s from './ProductImgItem.module.scss'
export interface ProductImgItemProps { export interface ProductImgItemProps {
preview: string url: string
name?: string alt?: string
} }
const ProductImgItem = ({ preview, name }: ProductImgItemProps) => { const ProductImgItem = ({ url, alt }: ProductImgItemProps) => {
return ( return (
<section className={s.productImgItem}> <section className={s.productImgItem}>
<ImgWithLink src={preview} alt={name} /> <ImgWithLink src={url} alt={alt} />
</section > </section >
) )
} }

View File

@@ -2,28 +2,13 @@ import React from 'react'
import { ResponsiveType } from 'react-multi-carousel' import { ResponsiveType } from 'react-multi-carousel'
import { CarouselCommon } from 'src/components/common' import { CarouselCommon } from 'src/components/common'
import ProductImgItem, { ProductImgItemProps } from '../ProductImgItem/ProductImgItem' import ProductImgItem, { ProductImgItemProps } from '../ProductImgItem/ProductImgItem'
import { useProductDetail } from 'src/components/hooks/product'
import s from './ProductImgs.module.scss' import s from './ProductImgs.module.scss'
import { ProductImage } from '@commerce/types/product';
interface Props { interface Props {
className?: string productImage: ProductImage[]
children?: any,
} }
const DATA = [
{
src: 'https://user-images.githubusercontent.com/76729908/133026929-199799fc-bd75-4445-a24d-15c0e41796eb.png',
alt: 'Meat',
},
{
src: 'https://user-images.githubusercontent.com/76729908/130574371-3b75fa72-9552-4605-aba9-a4b31cd9dce7.png',
alt: 'Broccoli',
},
{
src: 'https://user-images.githubusercontent.com/76729908/130574371-3b75fa72-9552-4605-aba9-a4b31cd9dce7.png',
alt: 'Broccoli',
}
]
const RESPONSIVE: ResponsiveType = { const RESPONSIVE: ResponsiveType = {
desktop: { desktop: {
@@ -32,12 +17,11 @@ const RESPONSIVE: ResponsiveType = {
slidesToSlide: 1, // optional, default to 1. slidesToSlide: 1, // optional, default to 1.
}, },
} }
const ProductImgs = ({ }: Props) => { const ProductImgs = ({ productImage }: Props) => {
const { productDetail } = useProductDetail()
return ( return (
<section className={s.productImgs}> <section className={s.productImgs}>
<CarouselCommon<ProductImgItemProps> <CarouselCommon<ProductImgItemProps>
data={productDetail?.assets ?? []} data={productImage}
itemKey="product-detail-img" itemKey="product-detail-img"
Component={ProductImgItem} Component={ProductImgItem}
responsive={RESPONSIVE} responsive={RESPONSIVE}

View File

@@ -1,31 +1,30 @@
import { Product } from '@commerce/types/product'
import React from 'react' import React from 'react'
import { ButtonCommon, LabelCommon, QuanittyInput } from 'src/components/common' import { ButtonCommon, LabelCommon, QuanittyInput } from 'src/components/common'
import { IconBuy } from 'src/components/icons' import { IconBuy } from 'src/components/icons'
import { LANGUAGE } from 'src/utils/language.utils' import { LANGUAGE } from 'src/utils/language.utils'
import { useProductDetail } from 'src/components/hooks/product'
import s from './ProductInfo.module.scss' import s from './ProductInfo.module.scss'
interface Props { interface Props {
className?: string productInfoDetail: Product
children?: any,
} }
const ProductInfo = ({ }: Props) => { const ProductInfo = ({ productInfoDetail }: Props) => {
const {productDetail} = useProductDetail() console.log(productInfoDetail)
return ( return (
<section className={s.productInfo}> <section className={s.productInfo}>
<div className={s.info}> <div className={s.info}>
<LabelCommon shape='half'>SEAFOOD</LabelCommon> <LabelCommon shape='half'>{productInfoDetail.collection}</LabelCommon>
<h2 className={s.heading}>{productDetail?.name}</h2> <h2 className={s.heading}>{productInfoDetail.name}</h2>
<div className={s.price}> <div className={s.price}>
<div className={s.old}> <div className={s.old}>
<span className={s.number}>Rp {productDetail?.variants[0].priceWithTax}</span> <span className={s.number}>Rp {productInfoDetail.price}</span>
<LabelCommon type='discount'>-15%</LabelCommon> <LabelCommon type='discount'>-15%</LabelCommon>
</div> </div>
<div className={s.current}>Rp {productDetail?.variants[0].price}</div> <div className={s.current}>Rp {productInfoDetail.price}</div>
</div> </div>
<div className={s.description}> <div className={s.description}>
{productDetail?.description} {productInfoDetail.description}
</div> </div>
</div> </div>
<div className={s.actions}> <div className={s.actions}>

View File

@@ -23,7 +23,6 @@ const ReleventProducts = ({ data, collections }: Props) => {
if (data.length === 0) { if (data.length === 0) {
return null return null
} }
return ( return (
<ListProductWithInfo <ListProductWithInfo
title="Relevant Products" title="Relevant Products"