Merge branch 'feature/m1-get-product-detail' of github.com:KieIO/grocery-vercel-commerce into feature/m3-add-product-to-cart-product-detail

This commit is contained in:
DatNguyen
2021-10-11 16:05:56 +07:00
15 changed files with 79 additions and 46 deletions

View File

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

View File

@@ -2,7 +2,7 @@ import { Product } from '@commerce/types/product'
import { OperationContext } from '@commerce/api/operations'
import { Provider, VendureConfig } from '../'
import { GetProductQuery } from '../../schema'
import { getProductQuery } from '../../utils/queries/get-product-query'
import { getProductQuery, getProductDetailQuery } from '../../utils/queries/get-product-query'
export default function getProductOperation({
commerce,
@@ -53,7 +53,8 @@ export default function getProductOperation({
displayName: og.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
}

View File

@@ -3303,7 +3303,7 @@ export type GetProductQuery = { __typename?: 'Query' } & {
variants: Array<
{ __typename?: 'ProductVariant' } & Pick<
ProductVariant,
'id' | 'priceWithTax' | 'currencyCode'
'id' | 'priceWithTax' | 'currencyCode' | 'price'
> & {
options: Array<
{ __typename?: 'ProductOption' } & Pick<

View File

@@ -39,6 +39,25 @@ export const getProductQuery = /* GraphQL */ `
facetValues {
id
}
collections {
id
}
}
}
`
export const getProductDetailQuery = /* GraphQL */ `
query GetProductDetail($slug: String! = "hand-trowel") {
product(slug: $slug) {
name
description
variants {
price
priceWithTax
}
assets {
preview
name
}
}
}
`

3
next-env.d.ts vendored
View File

@@ -1,6 +1,3 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

View File

@@ -26,6 +26,7 @@
"body-scroll-lock": "^3.1.5",
"classnames": "^2.3.1",
"cookie": "^0.4.1",
"dns": "^0.2.2",
"email-validator": "^2.0.4",
"eslint": "^7.32.0",
"eslint-config-next": "^11.1.2",
@@ -35,6 +36,7 @@
"lodash.debounce": "^4.0.8",
"lodash.random": "^3.2.0",
"lodash.throttle": "^4.1.1",
"net": "^1.0.2",
"next": "^11.0.0",
"next-seo": "^4.26.0",
"next-themes": "^0.0.14",

View File

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

View File

@@ -1,11 +1,12 @@
import commerce from '@lib/api/commerce';
import { GetStaticPropsContext } from 'next';
import { ProductCard } from '@commerce/types/product';
import { Layout, ListProductCardSkeleton } from 'src/components/common';
interface Props {
products: any
productDetail: ProductCard[],
}
export default function Home({ products }: Props) {
export default function Home({ productDetail }: Props) {
return (
<>
{/* <ListProductCardSkeleton /> */}

View File

@@ -0,0 +1 @@
export { default as useProductDetail } from './useProductDetail'

View File

@@ -0,0 +1,16 @@
import { GetProductQuery } from '@framework/schema'
import { getProductDetailQuery } from '@framework/utils/queries/get-product-query';
import gglFetcher from 'src/utils/gglFetcher'
import useSWR from 'swr'
interface ProductDetail {
slug: string
}
const useProductDetail = () => {
const { data, ...rest } = useSWR<GetProductQuery>([getProductDetailQuery],gglFetcher)
return { productDetail: data?.product, ...rest }
}
export default useProductDetail

View File

@@ -1,20 +1,28 @@
import React from 'react'
import React, { useMemo } from 'react';
import ProductImgs from './components/ProductImgs/ProductImgs'
import ProductInfo from './components/ProductInfo/ProductInfo'
import s from './ProductInfoDetail.module.scss'
import { Product } from '@commerce/types/product'
import { Collection } from '@framework/schema'
import { getCategoryNameFromCollectionId } from 'src/utils/funtion.utils';
interface Props {
className?: string
children?: any
productDetail: Product,
collections: Collection[]
}
const ProductInfoDetail = ({ }: Props) => {
const ProductInfoDetail = ({ productDetail, collections }: Props) => {
const dataWithCategoryName = useMemo(() => {
return {
...productDetail,
collection: getCategoryNameFromCollectionId(collections, productDetail.collectionIds ? productDetail.collectionIds[0] : undefined)
}
}, [productDetail, collections])
return (
<section className={s.productInfoDetail}>
<ProductImgs/>
<ProductInfo/>
<ProductImgs productImage={productDetail.images}/>
<ProductInfo productInfoDetail={dataWithCategoryName}/>
</section >
)
}
export default ProductInfoDetail

View File

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

View File

@@ -3,26 +3,12 @@ import { ResponsiveType } from 'react-multi-carousel'
import { CarouselCommon } from 'src/components/common'
import ProductImgItem, { ProductImgItemProps } from '../ProductImgItem/ProductImgItem'
import s from './ProductImgs.module.scss'
import { ProductImage } from '@commerce/types/product';
interface Props {
className?: string
children?: any,
productImage: ProductImage[]
}
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 = {
desktop: {
@@ -31,11 +17,11 @@ const RESPONSIVE: ResponsiveType = {
slidesToSlide: 1, // optional, default to 1.
},
}
const ProductImgs = ({ }: Props) => {
const ProductImgs = ({ productImage }: Props) => {
return (
<section className={s.productImgs}>
<CarouselCommon<ProductImgItemProps>
data={DATA}
data={productImage}
itemKey="product-detail-img"
Component={ProductImgItem}
responsive={RESPONSIVE}

View File

@@ -1,3 +1,4 @@
import { Product } from '@commerce/types/product'
import React from 'react'
import { ButtonCommon, LabelCommon, QuanittyInput } from 'src/components/common'
import { IconBuy } from 'src/components/icons'
@@ -5,25 +6,25 @@ import { LANGUAGE } from 'src/utils/language.utils'
import s from './ProductInfo.module.scss'
interface Props {
className?: string
children?: any,
productInfoDetail: Product
}
const ProductInfo = ({ }: Props) => {
const ProductInfo = ({ productInfoDetail }: Props) => {
console.log(productInfoDetail)
return (
<section className={s.productInfo}>
<div className={s.info}>
<LabelCommon shape='half'>SEAFOOD</LabelCommon>
<h2 className={s.heading}>SeaPAk</h2>
<LabelCommon shape='half'>{productInfoDetail.collection}</LabelCommon>
<h2 className={s.heading}>{productInfoDetail.name}</h2>
<div className={s.price}>
<div className={s.old}>
<span className={s.number}>Rp 32.000</span>
<span className={s.number}>Rp {productInfoDetail.price}</span>
<LabelCommon type='discount'>-15%</LabelCommon>
</div>
<div className={s.current}>Rp 27.500</div>
<div className={s.current}>Rp {productInfoDetail.price}</div>
</div>
<div className={s.description}>
In a large non-reactive dish, mix together the orange juice, soy sauce, olive oil, lemon juice, parsley
{productInfoDetail.description}
</div>
</div>
<div className={s.actions}>

View File

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