feat: featured products

:%s
This commit is contained in:
lytrankieio123
2021-10-04 19:36:47 +07:00
parent 6ad8f75c67
commit 47107e2702
9 changed files with 174 additions and 159 deletions

View File

@@ -1,4 +1,4 @@
import { CurrencyCode } from './../../vendure/schema.d'; import { CurrencyCode, FacetValue } from './../../vendure/schema.d';
import { FacetValueFilterInput, LogicalOperator, SearchResultSortParameter } from "@framework/schema" import { FacetValueFilterInput, LogicalOperator, SearchResultSortParameter } from "@framework/schema"
export type ProductImage = { export type ProductImage = {
@@ -54,9 +54,11 @@ export type ProductCard = {
imageSrc: string imageSrc: string
price: number price: number
currencyCode: CurrencyCode currencyCode: CurrencyCode
oldPrice?: number, oldPrice?: number
discount?: number discount?: number
weight?: number weight?: number
facetValueIds?: string[],
collectionIds?: string[],
// TODO: collection // TODO: collection
category?: string, category?: string,
isNotSell?: boolean isNotSell?: boolean

View File

@@ -1,3 +1,4 @@
import { FacetValue } from './schema.d';
export type Maybe<T> = T | null export type Maybe<T> = T | null
export type Exact<T extends { [key: string]: unknown }> = { export type Exact<T extends { [key: string]: unknown }> = {
[K in keyof T]: T[K] [K in keyof T]: T[K]
@@ -3038,7 +3039,7 @@ export type SearchResultFragment = { __typename?: 'SearchResult' } & Pick<
SearchResult, SearchResult,
'productId' | 'sku' | 'productName' | 'description' | 'slug' | 'sku' | 'currencyCode' 'productId' | 'sku' | 'productName' | 'description' | 'slug' | 'sku' | 'currencyCode'
| 'productAsset' | 'price' | 'priceWithTax' | 'currencyCode' | 'productAsset' | 'price' | 'priceWithTax' | 'currencyCode'
| 'collectionIds' | 'collectionIds' | 'facetValueIds' | 'collectionIds'
> & { > & {
productAsset?: Maybe< productAsset?: Maybe<
{ __typename?: 'SearchResultAsset' } & Pick< { __typename?: 'SearchResultAsset' } & Pick<

View File

@@ -19,6 +19,8 @@ export const searchResultFragment = /* GraphQL */ `
min min
max max
} }
} },
facetValueIds,
collectionIds,
} }
` `

View File

@@ -1,16 +1,17 @@
import { Product, ProductCard } from '@commerce/types/product'
import { Cart } from '@commerce/types/cart' import { Cart } from '@commerce/types/cart'
import { ProductCard } from '@commerce/types/product'
import { CartFragment, SearchResultFragment } from '../schema' import { CartFragment, SearchResultFragment } from '../schema'
export function normalizeSearchResult(item: SearchResultFragment): ProductCard { export function normalizeSearchResult(item: SearchResultFragment): ProductCard {
return { return {
id: item.productId, id: item.productId,
name: item.productName, name: item.productName,
slug: item.slug, slug: item.slug,
imageSrc: item.productAsset?.preview ? item.productAsset?.preview + '?w=800&mode=crop' : '', imageSrc: item.productAsset?.preview ? item.productAsset?.preview + '?w=800&mode=crop' : '',
price: (item.priceWithTax as any).min / 100, price: (item.priceWithTax as any).min / 100,
currencyCode: item.currencyCode, currencyCode: item.currencyCode,
facetValueIds: item.facetValueIds,
collectionIds: item.collectionIds,
// TODO: // TODO:
// oldPrice: item.price // oldPrice: item.price

View File

@@ -5,7 +5,7 @@ import { GetStaticPropsContext } from 'next';
import { Layout } from 'src/components/common'; import { Layout } from 'src/components/common';
import { FeaturedProductsCarousel, FreshProducts, HomeBanner, HomeCategories, HomeCollection, HomeCTA, HomeFeature, HomeRecipe, HomeSubscribe, HomeVideo } from 'src/components/modules/home'; import { FeaturedProductsCarousel, FreshProducts, HomeBanner, HomeCategories, HomeCollection, HomeCTA, HomeFeature, HomeRecipe, HomeSubscribe, HomeVideo } from 'src/components/modules/home';
import HomeSpice from 'src/components/modules/home/HomeSpice/HomeSpice'; import HomeSpice from 'src/components/modules/home/HomeSpice/HomeSpice';
import { getAllFeaturedFacetId, getFreshProductFacetId } from 'src/utils/funtion.utils'; import { getAllFeaturedFacetId, getFreshFacetId } from 'src/utils/funtion.utils';
interface Props { interface Props {
freshProducts: ProductCard[], freshProducts: ProductCard[],
@@ -18,11 +18,11 @@ export default function Home({ freshProducts, featuredProducts }: Props) {
<HomeBanner /> <HomeBanner />
<HomeFeature /> <HomeFeature />
<HomeCategories /> <HomeCategories />
<FreshProducts data={freshProducts}/> <FreshProducts data={freshProducts} />
<HomeCollection /> <HomeCollection />
<HomeVideo /> <HomeVideo />
<HomeSpice /> <HomeSpice />
<FeaturedProductsCarousel /> <FeaturedProductsCarousel data={featuredProducts} />
<HomeCTA /> <HomeCTA />
<HomeRecipe /> <HomeRecipe />
<HomeSubscribe /> <HomeSubscribe />
@@ -48,7 +48,7 @@ export async function getStaticProps({
const freshProductvariables: ProductVariables = {} const freshProductvariables: ProductVariables = {}
const freshFacetId = getFreshProductFacetId(facets) const freshFacetId = getFreshFacetId(facets)
if (freshFacetId) { if (freshFacetId) {
freshProductvariables.facetValueIds = [freshFacetId] freshProductvariables.facetValueIds = [freshFacetId]
@@ -60,6 +60,7 @@ export async function getStaticProps({
}) })
const allFeaturedFacetId = getAllFeaturedFacetId(facets) const allFeaturedFacetId = getAllFeaturedFacetId(facets)
console.log("featured** ", allFeaturedFacetId)
const featuredProductsPromise = commerce.getAllProducts({ const featuredProductsPromise = commerce.getAllProducts({
variables: { variables: {
facetValueIds: allFeaturedFacetId facetValueIds: allFeaturedFacetId
@@ -68,12 +69,15 @@ export async function getStaticProps({
preview, preview,
}) })
try { try {
const rs = await Promise.all([freshProductsPromise, featuredProductsPromise]) const rs = await Promise.all([
freshProductsPromise,
featuredProductsPromise,
])
return { return {
props: { props: {
facets,
freshProducts: freshFacetId ? rs[0].products : [], freshProducts: freshFacetId ? rs[0].products : [],
featuredProducts: rs[1].products featuredProducts: rs[1].products
}, },

View File

@@ -1,39 +1,53 @@
import { ProductCard } from '@commerce/types/product'
import Link from 'next/link'
import React from 'react' import React from 'react'
import { FeaturedProductProps } from 'src/utils/types.utils' import { ROUTE } from 'src/utils/constanst.utils'
import s from './FeaturedProductCard.module.scss'
import { LANGUAGE } from '../../../utils/language.utils'
import ButtonIconBuy from '../ButtonIconBuy/ButtonIconBuy'
import ButtonCommon from '../ButtonCommon/ButtonCommon'
import { ImgWithLink } from '..' import { ImgWithLink } from '..'
export interface FeaturedProductCardProps extends FeaturedProductProps { import { LANGUAGE } from '../../../utils/language.utils'
import ButtonCommon from '../ButtonCommon/ButtonCommon'
import ButtonIconBuy from '../ButtonIconBuy/ButtonIconBuy'
import s from './FeaturedProductCard.module.scss'
export interface FeaturedProductCardProps extends ProductCard {
buttonText?: string buttonText?: string
featuredFacetId?: string,
} }
const FeaturedProductCard = ({ const FeaturedProductCard = ({
imageSrc, imageSrc,
title, name,
subTitle, slug,
price, price,
originPrice, currencyCode,
buttonText = LANGUAGE.BUTTON_LABEL.BUY_NOW, buttonText = LANGUAGE.BUTTON_LABEL.BUY_NOW,
}: FeaturedProductCardProps) => { }: FeaturedProductCardProps) => {
return ( return (
<div className={s.featuredProductCardWarpper}> <div className={s.featuredProductCardWarpper}>
<div className={s.left}> <div className={s.left}>
<ImgWithLink src={imageSrc} alt={title}/> <Link href={`${ROUTE.PRODUCT_DETAIL}/${slug}`}>
<a>
<ImgWithLink src={imageSrc} alt={name} />
</a>
</Link>
</div> </div>
<div className={s.right}> <div className={s.right}>
<div className={s.rightTop}> <div className={s.rightTop}>
<div className={s.title}>{title}</div> <Link href={`${ROUTE.PRODUCT_DETAIL}/${slug}`}>
<div className={s.subTitle}>{subTitle}</div> <a>
<div className={s.title}>{name}</div>
</a>
</Link>
{/* TODO: */}
{/* <div className={s.subTitle}>{subTitle}</div> */}
<div className={s.priceWrapper}> <div className={s.priceWrapper}>
<div className={s.price}>{price} </div> <div className={s.price}>{price} {currencyCode}</div>
<div className={s.originPrice}>{originPrice} </div> {/* TODO: */}
{/* <div className={s.originPrice}>{originPrice} </div> */}
</div> </div>
</div> </div>
<div className={s.buttonWarpper}> <div className={s.buttonWarpper}>
<div className={s.icon}> <div className={s.icon}>
<ButtonIconBuy size='default'/> <ButtonIconBuy size='default' />
</div> </div>
<div className={s.button}> <div className={s.button}>
<ButtonCommon>{buttonText}</ButtonCommon> <ButtonCommon>{buttonText}</ButtonCommon>

View File

@@ -1,31 +1,15 @@
import { ProductCard } from '@commerce/types/product'
import React from 'react' import React from 'react'
import { ResponsiveType } from 'react-multi-carousel' import { ResponsiveType } from 'react-multi-carousel'
import { CarouselCommon, FeaturedProductCard,HeadingCommon} from 'src/components/common' import { CarouselCommon, FeaturedProductCard,HeadingCommon} from 'src/components/common'
import { FeaturedProductCardProps } from 'src/components/common/FeaturedProductCard/FeaturedProductCard' import { FeaturedProductCardProps } from 'src/components/common/FeaturedProductCard/FeaturedProductCard'
import s from "./FeaturedProductsCarousel.module.scss" import s from "./FeaturedProductsCarousel.module.scss"
interface FeaturedProductsCarouselProps { interface FeaturedProductsCarouselProps {
title?: string title?: string,
data: ProductCard[]
} }
const dataDemo:FeaturedProductCardProps[] = [{
title: "Sale 25% Coffee Bean",
subTitle: "50 first Orders within a day",
originPrice: "$20.00",
price: "$14.00",
imageSrc: "https://user-images.githubusercontent.com/76099413/133043628-db7813f9-1bb7-4ee1-b028-dc4295563494.png"
},{
title: "Sale 20% Fruits",
subTitle: "50 first Orders within a day",
originPrice: "$20.00",
price: "$14.00",
imageSrc: "https://user-images.githubusercontent.com/76099413/133043630-07a353b9-573d-4c1d-b1de-2c932e3f14f7.png"
},{
title: "Sale 25% Coffee Bean",
subTitle: "50 first Orders within a day",
originPrice: "$20.00",
price: "$14.00",
imageSrc: "https://user-images.githubusercontent.com/76099413/133043633-954c105b-c703-4e5c-8f5f-7943ad633ff0.png"
}]
const RESPONSIVE: ResponsiveType = { const RESPONSIVE: ResponsiveType = {
hugeScreen: { hugeScreen: {
breakpoint: { max: 9999, min: 1500 }, breakpoint: { max: 9999, min: 1500 },
@@ -78,13 +62,13 @@ const dataDemo:FeaturedProductCardProps[] = [{
}, },
} }
const FeaturedProductsCarousel = ({title="Featured Products"}: FeaturedProductsCarouselProps) => { const FeaturedProductsCarousel = ({title="Featured Products", data}: FeaturedProductsCarouselProps) => {
return ( return (
<div className={s.warpper}> <div className={s.warpper}>
<div className={s.heading}> <div className={s.heading}>
<HeadingCommon>{title}</HeadingCommon> <HeadingCommon>{title}</HeadingCommon>
</div> </div>
<CarouselCommon<FeaturedProductCardProps> data={dataDemo} Component={FeaturedProductCard} itemKey="featured-products" responsive={RESPONSIVE}/> <CarouselCommon<FeaturedProductCardProps> data={data} Component={FeaturedProductCard} itemKey="featured-products" responsive={RESPONSIVE}/>
</div> </div>
) )
} }

View File

@@ -4,41 +4,41 @@ export const BLUR_DATA_IMG = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEA
export const DEFAULT_IMG = DefaultImg export const DEFAULT_IMG = DefaultImg
export const SOCIAL_LINKS = { export const SOCIAL_LINKS = {
FB: 'FB', FB: 'FB',
TWITTER: 'TWITTER', TWITTER: 'TWITTER',
YOUTUBE: 'YOUTUBE', YOUTUBE: 'YOUTUBE',
IG: 'IG', IG: 'IG',
} }
export const ROUTE = { export const ROUTE = {
HOME: '/', HOME: '/',
ABOUT: '/about', ABOUT: '/about',
ACCOUNT: '/account', ACCOUNT: '/account',
PRODUCTS: '/products', PRODUCTS: '/products',
PRODUCT_DETAIL: '/product', PRODUCT_DETAIL: '/product',
BLOGS: '/blogs',
BLOG_DETAIL: '/blog',
RECIPES: '/recipes', BLOGS: '/blogs',
RECIPE_DETAIL: '/recipe', BLOG_DETAIL: '/blog',
NOTIFICATION: '/notifications', RECIPES: '/recipes',
BUSSINESS: '/bussiness', RECIPE_DETAIL: '/recipe',
CONTACT: '/contact',
CHECKOUT: '/checkout', NOTIFICATION: '/notifications',
FAQ: '/faq', BUSSINESS: '/bussiness',
CUSTOMER_SERVICE: '/customer-service', CONTACT: '/contact',
TERM_CONDITION: '/term-condition', CHECKOUT: '/checkout',
PRIVACY_POLICY: '/privacy-policy', FAQ: '/faq',
FORGOT_PASSWORD: '/forgot-password' CUSTOMER_SERVICE: '/customer-service',
TERM_CONDITION: '/term-condition',
PRIVACY_POLICY: '/privacy-policy',
FORGOT_PASSWORD: '/forgot-password'
} }
export const ACCOUNT_TAB = { export const ACCOUNT_TAB = {
CUSTOMER_INFO: '', CUSTOMER_INFO: '',
ORDER: 'orders', ORDER: 'orders',
FAVOURITE: 'wishlist', FAVOURITE: 'wishlist',
} }
export const LOCAL_STORAGE_KEY = { export const LOCAL_STORAGE_KEY = {
@@ -46,101 +46,99 @@ export const LOCAL_STORAGE_KEY = {
} }
export const QUERY_KEY = { export const QUERY_KEY = {
TAB: 'tab', TAB: 'tab',
CATEGORY: 'category', CATEGORY: 'category',
BRAND: 'brand', BRAND: 'brand',
FEATURED: 'feature', FEATURED: 'feature',
SORTBY:'sortby', SORTBY: 'sortby',
RECIPES:'recipes' RECIPES: 'recipes'
} }
export enum ProductFeature { export enum ProductFeature {
BestSellers = 'Best Sellers', BestSellers = 'Best Sellers',
Sales = 'Sales', Sales = 'Sales',
NewItem = 'New Item', NewItem = 'New Item',
Viewed = 'Viewed', Viewed = 'Viewed',
} }
export const KEY = { export const KEY = {
ENTER: 'Enter', ENTER: 'Enter',
} }
export const OPTION_ALL = 'all'; export const OPTION_ALL = 'all';
export const DEFAULT_PAGE_SIZE=20; export const DEFAULT_PAGE_SIZE = 20;
export const CATEGORY = [ export const CATEGORY = [
{ {
name: 'All', name: 'All',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=${OPTION_ALL}`, link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=${OPTION_ALL}`,
}, },
{ {
name: 'Veggie', name: 'Veggie',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=veggie`, link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=veggie`,
}, },
{ {
name: 'Seafood', name: 'Seafood',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=seafood`, link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=seafood`,
}, },
{ {
name: 'Frozen', name: 'Frozen',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=frozen`, link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=frozen`,
}, },
{ {
name: 'Coffee Bean', name: 'Coffee Bean',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=coffee_bean`, link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=coffee_bean`,
}, },
{ {
name: 'Sauce', name: 'Sauce',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=sauce`, link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=sauce`,
}, },
] ]
export const BRAND = [
{
name: 'Maggi',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=maggi`,
},
{
name: 'Chomilex',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=chomilex`,
},
{
name: 'Chinsu',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=chinsu`,
},
]
export const FACET = { export const BRAND = [
FEATURE: { {
PARENT_NAME: 'Featured', name: 'Maggi',
FRESH: 'Fresh', link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=maggi`,
BEST_SELLERS: 'Best seller' },
} {
name: 'Chomilex',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=chomilex`,
},
{
name: 'Chinsu',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=chinsu`,
},
]
export const CODE_FACET_FEATURED = 'featured'
export const CODE_FACET_FEATURED_VARIANT = {
FRESH: 'fresh',
BEST_SELLERS: 'best-sellers'
} }
export const FEATURED = [ export const FEATURED = [
{ {
name: 'Best Sellers', name: 'Best Sellers',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.FEATURED}=best_sellers`, link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.FEATURED}=best_sellers`,
}, },
{ {
name: 'Sales', name: 'Sales',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.FEATURED}=sales`, link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.FEATURED}=sales`,
}, },
{ {
name: 'New Item', name: 'New Item',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.FEATURED}=new_item`, link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.FEATURED}=new_item`,
}, },
{ {
name: 'Viewed', name: 'Viewed',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.FEATURED}=viewed`, link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.FEATURED}=viewed`,
}, },
] ]
export const DEFAULT_BLOG_PAGE_SIZE=6;
export const FILTER_PAGE = [ROUTE.HOME,ROUTE.PRODUCTS] export const DEFAULT_BLOG_PAGE_SIZE = 6;
export const FILTER_PAGE = [ROUTE.HOME, ROUTE.PRODUCTS]
export const STATE_OPTIONS = [ export const STATE_OPTIONS = [
{ {

View File

@@ -1,6 +1,6 @@
import { FacetValue } from './../../framework/vendure/schema.d';
import { Facet } from "@commerce/types/facet"; import { Facet } from "@commerce/types/facet";
import { FACET } from "./constanst.utils"; import { FacetValue } from './../../framework/vendure/schema.d';
import { CODE_FACET_FEATURED, CODE_FACET_FEATURED_VARIANT } from "./constanst.utils";
export function isMobile() { export function isMobile() {
return window.innerWidth < 768 return window.innerWidth < 768
@@ -14,15 +14,24 @@ export function removeItem<T>(arr: Array<T>, value: T): Array<T> {
return [...arr]; return [...arr];
} }
export function getFreshProductFacetId(facets: Facet[]) { function findFacetByCode(code: string, facets?: Facet) {
const featuredFacet = facets.find((item: Facet) => item.name === FACET.FEATURE.PARENT_NAME) return facets?.values.find((item: FacetValue) => item.code === code)
const freshFacetValue = featuredFacet?.values.find((item: FacetValue) => item.name === FACET.FEATURE.FRESH) }
export function getFeaturedFacetId(facets: Facet[]) {
const featuredFacet = facets.find((item: Facet) => item.code === CODE_FACET_FEATURED)
return featuredFacet?.id
}
export function getFreshFacetId(facets: Facet[]) {
const featuredFacet = facets.find((item: Facet) => item.code === CODE_FACET_FEATURED)
const freshFacetValue = findFacetByCode(CODE_FACET_FEATURED_VARIANT.FRESH, featuredFacet)
return freshFacetValue?.id return freshFacetValue?.id
} }
export function getAllFeaturedFacetId(facets: Facet[]) { export function getAllFeaturedFacetId(facets: Facet[]) {
const featuredFacet = facets.find((item: Facet) => item.name === FACET.FEATURE.PARENT_NAME) const featuredFacet = facets.find((item: Facet) => item.code === CODE_FACET_FEATURED)
const rs = featuredFacet?.values.map((item: FacetValue) => item.id) const rs = featuredFacet?.values.map((item: FacetValue) => item.id)
return rs return rs