mirror of
https://github.com/vercel/commerce.git
synced 2025-07-23 04:36:49 +00:00
✨ feat: featured products
:%s
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { CurrencyCode } from './../../vendure/schema.d';
|
||||
import { CurrencyCode, FacetValue } from './../../vendure/schema.d';
|
||||
import { FacetValueFilterInput, LogicalOperator, SearchResultSortParameter } from "@framework/schema"
|
||||
|
||||
export type ProductImage = {
|
||||
@@ -54,9 +54,11 @@ export type ProductCard = {
|
||||
imageSrc: string
|
||||
price: number
|
||||
currencyCode: CurrencyCode
|
||||
oldPrice?: number,
|
||||
oldPrice?: number
|
||||
discount?: number
|
||||
weight?: number
|
||||
facetValueIds?: string[],
|
||||
collectionIds?: string[],
|
||||
// TODO: collection
|
||||
category?: string,
|
||||
isNotSell?: boolean
|
||||
|
3
framework/vendure/schema.d.ts
vendored
3
framework/vendure/schema.d.ts
vendored
@@ -1,3 +1,4 @@
|
||||
import { FacetValue } from './schema.d';
|
||||
export type Maybe<T> = T | null
|
||||
export type Exact<T extends { [key: string]: unknown }> = {
|
||||
[K in keyof T]: T[K]
|
||||
@@ -3038,7 +3039,7 @@ export type SearchResultFragment = { __typename?: 'SearchResult' } & Pick<
|
||||
SearchResult,
|
||||
'productId' | 'sku' | 'productName' | 'description' | 'slug' | 'sku' | 'currencyCode'
|
||||
| 'productAsset' | 'price' | 'priceWithTax' | 'currencyCode'
|
||||
| 'collectionIds'
|
||||
| 'collectionIds' | 'facetValueIds' | 'collectionIds'
|
||||
> & {
|
||||
productAsset?: Maybe<
|
||||
{ __typename?: 'SearchResultAsset' } & Pick<
|
||||
|
@@ -19,6 +19,8 @@ export const searchResultFragment = /* GraphQL */ `
|
||||
min
|
||||
max
|
||||
}
|
||||
}
|
||||
},
|
||||
facetValueIds,
|
||||
collectionIds,
|
||||
}
|
||||
`
|
||||
|
@@ -1,16 +1,17 @@
|
||||
import { Product, ProductCard } from '@commerce/types/product'
|
||||
import { Cart } from '@commerce/types/cart'
|
||||
import { ProductCard } from '@commerce/types/product'
|
||||
import { CartFragment, SearchResultFragment } from '../schema'
|
||||
|
||||
export function normalizeSearchResult(item: SearchResultFragment): ProductCard {
|
||||
return {
|
||||
|
||||
id: item.productId,
|
||||
name: item.productName,
|
||||
slug: item.slug,
|
||||
imageSrc: item.productAsset?.preview ? item.productAsset?.preview + '?w=800&mode=crop' : '',
|
||||
price: (item.priceWithTax as any).min / 100,
|
||||
currencyCode: item.currencyCode,
|
||||
facetValueIds: item.facetValueIds,
|
||||
collectionIds: item.collectionIds,
|
||||
|
||||
// TODO:
|
||||
// oldPrice: item.price
|
||||
|
@@ -5,7 +5,7 @@ import { GetStaticPropsContext } from 'next';
|
||||
import { Layout } from 'src/components/common';
|
||||
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 { getAllFeaturedFacetId, getFreshProductFacetId } from 'src/utils/funtion.utils';
|
||||
import { getAllFeaturedFacetId, getFreshFacetId } from 'src/utils/funtion.utils';
|
||||
|
||||
interface Props {
|
||||
freshProducts: ProductCard[],
|
||||
@@ -22,7 +22,7 @@ export default function Home({ freshProducts, featuredProducts }: Props) {
|
||||
<HomeCollection />
|
||||
<HomeVideo />
|
||||
<HomeSpice />
|
||||
<FeaturedProductsCarousel />
|
||||
<FeaturedProductsCarousel data={featuredProducts} />
|
||||
<HomeCTA />
|
||||
<HomeRecipe />
|
||||
<HomeSubscribe />
|
||||
@@ -48,7 +48,7 @@ export async function getStaticProps({
|
||||
|
||||
|
||||
const freshProductvariables: ProductVariables = {}
|
||||
const freshFacetId = getFreshProductFacetId(facets)
|
||||
const freshFacetId = getFreshFacetId(facets)
|
||||
|
||||
if (freshFacetId) {
|
||||
freshProductvariables.facetValueIds = [freshFacetId]
|
||||
@@ -60,6 +60,7 @@ export async function getStaticProps({
|
||||
})
|
||||
|
||||
const allFeaturedFacetId = getAllFeaturedFacetId(facets)
|
||||
console.log("featured** ", allFeaturedFacetId)
|
||||
const featuredProductsPromise = commerce.getAllProducts({
|
||||
variables: {
|
||||
facetValueIds: allFeaturedFacetId
|
||||
@@ -68,12 +69,15 @@ export async function getStaticProps({
|
||||
preview,
|
||||
})
|
||||
|
||||
|
||||
try {
|
||||
const rs = await Promise.all([freshProductsPromise, featuredProductsPromise])
|
||||
const rs = await Promise.all([
|
||||
freshProductsPromise,
|
||||
featuredProductsPromise,
|
||||
])
|
||||
|
||||
return {
|
||||
props: {
|
||||
facets,
|
||||
freshProducts: freshFacetId ? rs[0].products : [],
|
||||
featuredProducts: rs[1].products
|
||||
},
|
||||
|
@@ -1,34 +1,48 @@
|
||||
import { ProductCard } from '@commerce/types/product'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
import { FeaturedProductProps } from 'src/utils/types.utils'
|
||||
import s from './FeaturedProductCard.module.scss'
|
||||
import { LANGUAGE } from '../../../utils/language.utils'
|
||||
import ButtonIconBuy from '../ButtonIconBuy/ButtonIconBuy'
|
||||
import ButtonCommon from '../ButtonCommon/ButtonCommon'
|
||||
import { ROUTE } from 'src/utils/constanst.utils'
|
||||
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
|
||||
featuredFacetId?: string,
|
||||
}
|
||||
|
||||
const FeaturedProductCard = ({
|
||||
imageSrc,
|
||||
title,
|
||||
subTitle,
|
||||
name,
|
||||
slug,
|
||||
price,
|
||||
originPrice,
|
||||
currencyCode,
|
||||
buttonText = LANGUAGE.BUTTON_LABEL.BUY_NOW,
|
||||
}: FeaturedProductCardProps) => {
|
||||
return (
|
||||
<div className={s.featuredProductCardWarpper}>
|
||||
<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 className={s.right}>
|
||||
<div className={s.rightTop}>
|
||||
<div className={s.title}>{title}</div>
|
||||
<div className={s.subTitle}>{subTitle}</div>
|
||||
<Link href={`${ROUTE.PRODUCT_DETAIL}/${slug}`}>
|
||||
<a>
|
||||
<div className={s.title}>{name}</div>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
{/* TODO: */}
|
||||
{/* <div className={s.subTitle}>{subTitle}</div> */}
|
||||
<div className={s.priceWrapper}>
|
||||
<div className={s.price}>{price} </div>
|
||||
<div className={s.originPrice}>{originPrice} </div>
|
||||
<div className={s.price}>{price} {currencyCode}</div>
|
||||
{/* TODO: */}
|
||||
{/* <div className={s.originPrice}>{originPrice} </div> */}
|
||||
</div>
|
||||
</div>
|
||||
<div className={s.buttonWarpper}>
|
||||
|
@@ -1,31 +1,15 @@
|
||||
import { ProductCard } from '@commerce/types/product'
|
||||
import React from 'react'
|
||||
import { ResponsiveType } from 'react-multi-carousel'
|
||||
import { CarouselCommon, FeaturedProductCard,HeadingCommon} from 'src/components/common'
|
||||
import { FeaturedProductCardProps } from 'src/components/common/FeaturedProductCard/FeaturedProductCard'
|
||||
import s from "./FeaturedProductsCarousel.module.scss"
|
||||
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 = {
|
||||
hugeScreen: {
|
||||
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 (
|
||||
<div className={s.warpper}>
|
||||
<div className={s.heading}>
|
||||
<HeadingCommon>{title}</HeadingCommon>
|
||||
</div>
|
||||
<CarouselCommon<FeaturedProductCardProps> data={dataDemo} Component={FeaturedProductCard} itemKey="featured-products" responsive={RESPONSIVE}/>
|
||||
<CarouselCommon<FeaturedProductCardProps> data={data} Component={FeaturedProductCard} itemKey="featured-products" responsive={RESPONSIVE}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@@ -111,12 +111,10 @@ export const CATEGORY = [
|
||||
},
|
||||
]
|
||||
|
||||
export const FACET = {
|
||||
FEATURE: {
|
||||
PARENT_NAME: 'Featured',
|
||||
FRESH: 'Fresh',
|
||||
BEST_SELLERS: 'Best seller'
|
||||
}
|
||||
export const CODE_FACET_FEATURED = 'featured'
|
||||
export const CODE_FACET_FEATURED_VARIANT = {
|
||||
FRESH: 'fresh',
|
||||
BEST_SELLERS: 'best-sellers'
|
||||
}
|
||||
|
||||
export const FEATURED = [
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { FacetValue } from './../../framework/vendure/schema.d';
|
||||
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() {
|
||||
return window.innerWidth < 768
|
||||
@@ -14,15 +14,24 @@ export function removeItem<T>(arr: Array<T>, value: T): Array<T> {
|
||||
return [...arr];
|
||||
}
|
||||
|
||||
export function getFreshProductFacetId(facets: Facet[]) {
|
||||
const featuredFacet = facets.find((item: Facet) => item.name === FACET.FEATURE.PARENT_NAME)
|
||||
const freshFacetValue = featuredFacet?.values.find((item: FacetValue) => item.name === FACET.FEATURE.FRESH)
|
||||
function findFacetByCode(code: string, facets?: Facet) {
|
||||
return facets?.values.find((item: FacetValue) => item.code === code)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
return rs
|
||||
|
Reference in New Issue
Block a user