Merge pull request #60 from KieIO/fixbug-13/9/2021-datnguyen

Refactor Carousel Common
This commit is contained in:
lytrankieio123
2021-09-21 14:13:00 +07:00
committed by GitHub
39 changed files with 1795 additions and 1544 deletions

3
next-env.d.ts vendored
View File

@@ -1,3 +1,6 @@
/// <reference types="next" /> /// <reference types="next" />
/// <reference types="next/types/global" /> /// <reference types="next/types/global" />
/// <reference types="next/image-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

@@ -31,7 +31,6 @@
"eslint-config-next": "^11.1.2", "eslint-config-next": "^11.1.2",
"immutability-helper": "^3.1.1", "immutability-helper": "^3.1.1",
"js-cookie": "^2.2.1", "js-cookie": "^2.2.1",
"keen-slider": "^5.5.1",
"lodash.debounce": "^4.0.8", "lodash.debounce": "^4.0.8",
"lodash.random": "^3.2.0", "lodash.random": "^3.2.0",
"lodash.throttle": "^4.1.1", "lodash.throttle": "^4.1.1",
@@ -44,6 +43,7 @@
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-fast-marquee": "^1.1.4", "react-fast-marquee": "^1.1.4",
"react-merge-refs": "^1.1.0", "react-merge-refs": "^1.1.0",
"react-multi-carousel": "^2.6.5",
"react-player": "^2.9.0", "react-player": "^2.9.0",
"react-use-measure": "^2.0.4", "react-use-measure": "^2.0.4",
"sass": "^1.38.0", "sass": "^1.38.0",

View File

@@ -2,7 +2,6 @@ import { ThemeProvider } from 'next-themes';
import type { AppProps } from 'next/app'; import type { AppProps } from 'next/app';
import React, { FC, useEffect } from 'react'; import React, { FC, useEffect } from 'react';
import { CustomShapeSvg, Head } from 'src/components/common'; import { CustomShapeSvg, Head } from 'src/components/common';
import 'keen-slider/keen-slider.min.css';
import '../src/styles/main.scss'; import '../src/styles/main.scss';

View File

@@ -1,5 +1,5 @@
import { Layout } from 'src/components/common'; import { Layout } from 'src/components/common';
import { HomeBanner, HomeCategories, HomeCollection, HomeCTA, HomeFeature, HomeRecipe, HomeSubscribe, HomeVideo } from 'src/components/modules/home'; import { FeaturedProductsCarousel, 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';
export default function Home() { export default function Home() {
@@ -10,6 +10,7 @@ export default function Home() {
<HomeCategories /> <HomeCategories />
<HomeCollection /> <HomeCollection />
<HomeVideo /> <HomeVideo />
<FeaturedProductsCarousel/>
<HomeSpice/> <HomeSpice/>
<HomeCTA /> <HomeCTA />
<HomeRecipe /> <HomeRecipe />

View File

@@ -2,6 +2,7 @@ import {
FeaturedProductCard, FeaturedProductCard,
Layout Layout
} from 'src/components/common'; } from 'src/components/common';
import { HomeBanner } from 'src/components/modules/home';
// import { RecipeListPage } from 'src/components/modules/recipes'; // import { RecipeListPage } from 'src/components/modules/recipes';
import { OPTION_ALL, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils'; import { OPTION_ALL, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils';
import { PRODUCT_DATA_TEST, PRODUCT_DATA_TEST_PAGE } from 'src/utils/demo-data'; import { PRODUCT_DATA_TEST, PRODUCT_DATA_TEST_PAGE } from 'src/utils/demo-data';
@@ -44,8 +45,7 @@ const BRAND = [
{ {
name: 'Chinsu', name: 'Chinsu',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=frozen`, link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=frozen`,
} }]
];
const FEATURED = [ const FEATURED = [
@@ -79,6 +79,7 @@ export default function Test() {
subTitle="50 first orders within a day" subTitle="50 first orders within a day"
price={data.price} price={data.price}
originPrice="$20.00" /> originPrice="$20.00" />
<HomeBanner/>
</> </>
) )
} }

View File

@@ -0,0 +1,3 @@
.bannerWrap {
@apply w-full;
}

View File

@@ -1,16 +1,21 @@
import { TOptionsEvents } from 'keen-slider'
import React, { memo } from 'react' import React, { memo } from 'react'
import { ResponsiveType } from 'react-multi-carousel'
import CarouselCommon from '../CarouselCommon/CarouselCommon' import CarouselCommon from '../CarouselCommon/CarouselCommon'
import BannerItem, { BannerItemProps } from './BannerItem/BannerItem' import BannerItem, { BannerItemProps } from './BannerItem/BannerItem'
import s from './Banner.module.scss'
interface Props { interface Props {
data: BannerItemProps[], data: BannerItemProps[],
} }
const option: TOptionsEvents = { const RESPONSIVE:ResponsiveType = {
slidesPerView: 1, desktop: {
mode: 'free', breakpoint: { max: 9999, min: 0 },
} items: 1,
slidesToSlide:1
},
};
const Banner = memo(({ data }: Props) => { const Banner = memo(({ data }: Props) => {
if (data.length === 1) { if (data.length === 1) {
const item = data[0] const item = data[0]
@@ -24,13 +29,15 @@ const Banner = memo(({ data }: Props) => {
/> />
} }
return ( return (
<CarouselCommon<BannerItemProps> <div className={s.bannerWrap}>
data={data} <CarouselCommon<BannerItemProps>
itemKey="banner" data={data}
Component={BannerItem} itemKey="banner"
option={option} Component={BannerItem}
isDot={true} responsive={RESPONSIVE}
/> showDots={true}
/>
</div>
) )
}) })

View File

@@ -1,8 +1,11 @@
@import "../../../../styles/utilities"; @import "../../../../styles/utilities";
.bannerItem { .bannerItem {
@apply bg-primary-light shape-common-lg overflow-hidden; @apply bg-primary-light shape-common-lg overflow-hidden w-full;
padding: 0; padding: 0;
@screen lg {
max-height: 42rem;
}
&.large { &.large {
margin-bottom: 2.8rem; margin-bottom: 2.8rem;
background-image: url("./pattern.svg"); background-image: url("./pattern.svg");

View File

@@ -1,59 +1,75 @@
@import '../../../styles/utilities'; @import '../../../styles/utilities';
.navigationWrapper { .navigationWrapper {
@apply relative; @apply relative;
overflow: hidden;
min-height: theme('caroucel.arrow-height'); min-height: theme('caroucel.arrow-height');
.isPadding { .isPadding {
@apply spacing-horizontal; // @apply spacing-horizontal;
}
.showDots {
padding-bottom: 2.4rem;
}
:global {
.react-multi-carousel-dot-list {
li {
button{
outline: none;
&:focus {
outline: none;
}
}
}
}
} }
:global(.customArrow) { :global(.customArrow) {
width: 64px; width: 64px;
height: 64px; height: 64px;
border-radius: .8rem; border-radius: 0.8rem;
backdrop-filter: saturate(180%) blur(10px); backdrop-filter: saturate(180%) blur(10px);
&:focus { &:focus {
outline: none; outline: none;
} }
@apply absolute top-1/2 bg-background-arrow transform -translate-y-1/2 flex justify-center items-center transition duration-100; @apply absolute top-1/2 bg-background-arrow transform -translate-y-1/2 flex justify-center items-center transition duration-100;
&:global(.leftArrow) { &:global(.leftArrow) {
@apply hidden left-0; @apply hidden left-0;
@screen md { @screen md {
@apply flex @apply flex;
} }
} }
&:global(.rightArrow) { &:global(.rightArrow) {
@apply hidden right-0; @apply hidden right-0;
@screen md { @screen md {
@apply flex; @apply flex;
} }
} }
&:global(.isDisabledArrow) { &:global(.isDisabledArrow) {
@apply hidden; @apply hidden;
} }
} }
:global { :global {
.dots { .dots {
display: flex; display: flex;
padding: 1rem 0; padding: 1rem 0;
justify-content: center; justify-content: center;
} }
.dot { .dot {
border: none; border: none;
width: 1rem; width: 1rem;
height: 1rem; height: 1rem;
background: #c5c5c5; background: #c5c5c5;
border-radius: 50%; border-radius: 50%;
margin: 0 0.5rem; margin: 0 0.5rem;
padding: 0.5rem; padding: 0.5rem;
cursor: pointer; cursor: pointer;
} }
.dot:focus { .dot:focus {
outline: none; outline: none;
} }
.dot.active { .dot.active {
background: #000; background: #000;
} }
} }
} }

View File

@@ -1,85 +1,87 @@
import { useKeenSlider } from 'keen-slider/react' import React, { useEffect, useRef } from 'react'
import React, { useEffect } from 'react'
import 'keen-slider/keen-slider.min.css'
import { CustomCarouselArrow } from './CustomArrow/CustomCarouselArrow' import { CustomCarouselArrow } from './CustomArrow/CustomCarouselArrow'
import s from './CarouselCommon.module.scss' import s from './CarouselCommon.module.scss'
import { TOptionsEvents } from 'keen-slider'
import classNames from 'classnames' import classNames from 'classnames'
import CustomDot from './CustomDot/CustomDot' import Carousel from 'react-multi-carousel'
export interface CarouselCommonProps<T> { import 'react-multi-carousel/lib/styles.css'
import {
ResponsiveType,
CarouselProps,
ButtonGroupProps,
} from 'react-multi-carousel/lib/types'
export interface CarouselCommonProps<T>
extends Omit<CarouselProps, 'children' | 'responsive'> {
data: T[] data: T[]
Component: React.ComponentType<T> Component: React.ComponentType<T>
isArrow?: Boolean
isDot?: Boolean
itemKey: String itemKey: String
option: TOptionsEvents
keenClassname?: string
isPadding?: boolean isPadding?: boolean
defaultComponentProps?: object defaultComponentProps?: object
responsive?: ResponsiveType
}
const RESPONSIVE = {
desktop: {
breakpoint: { max: 3000, min: 1024 },
items: 3,
slidesToSlide: 3, // optional, default to 1.
},
tablet: {
breakpoint: { max: 1024, min: 464 },
items: 2,
slidesToSlide: 2, // optional, default to 1.
},
mobile: {
breakpoint: { max: 464, min: 0 },
items: 1,
slidesToSlide: 1, // optional, default to 1.
},
} }
const CarouselCommon = <T,>({ const CarouselCommon = <T,>({
data, data = [],
Component, Component,
itemKey, itemKey,
keenClassname,
isPadding = false,
isArrow = true,
isDot = false,
defaultComponentProps, defaultComponentProps,
option: { slideChanged,slidesPerView, ...sliderOption }, responsive = RESPONSIVE,
showDots,
isPadding,
arrows,
...props
}: CarouselCommonProps<T>) => { }: CarouselCommonProps<T>) => {
const [currentSlide, setCurrentSlide] = React.useState(0) const carousel = useRef<Carousel>(null)
const [dotArr, setDotArr] = React.useState<number[]>([])
const [sliderRef, slider] = useKeenSlider<HTMLDivElement>({
...sliderOption,
slidesPerView,
slideChanged(s) {
setCurrentSlide(s.details().relativeSlide)
},
})
useEffect(() => {
if(isDot && slider && data){
let array:number[]
let number = data.length - Math.floor(slider.details().slidesPerView - 1)
if(number<1){
number = 1
}
array = [...Array(number).keys()]
setDotArr(array)
}
}, [isDot,slider,data])
const handleRightArrowClick = () => { const handleRightArrowClick = () => {
slider.next() carousel.current?.next(carousel.current.props.slidesToSlide||1)
} }
const handleLeftArrowClick = () => { const handleLeftArrowClick = () => {
slider.prev() carousel.current?.previous(carousel.current.props.slidesToSlide||1)
}
const onDotClick = (index:number) => {
slider.moveToSlideRelative(index)
} }
return ( return (
<div className={s.navigationWrapper}> <div className={s.navigationWrapper}>
<div <Carousel
ref={sliderRef} {...props}
className={classNames('keen-slider', keenClassname, { ref={carousel}
showDots={showDots}
customButtonGroup={<CarouselButtonGroup />}
renderButtonGroupOutside
sliderClass={''}
containerClass={classNames({
[s.showDots]: showDots,
[s.isPadding]: isPadding, [s.isPadding]: isPadding,
})} })}
responsive={responsive}
arrows={false}
renderDotsOutside={true}
ssr={true}
// customLeftArrow={<CustomCarouselArrow side="left" />}
// customRightArrow={<CustomCarouselArrow side="right" />}
> >
{data?.map((props, index) => { {data.map((props, index) => {
const allProps = defaultComponentProps ? { ...props, ...defaultComponentProps } : props const allProps = defaultComponentProps
return ( ? { ...props, ...defaultComponentProps }
<div className="keen-slider__slide" key={`${itemKey}-${index}`}> : props
<Component {...allProps} /> return <Component {...allProps} key={`${itemKey}-${index}`} />
</div>
)
})} })}
</div> </Carousel>
{slider && isArrow && ( {carousel && arrows && (
<> <>
<CustomCarouselArrow <CustomCarouselArrow
side="right" side="right"
@@ -91,7 +93,7 @@ const CarouselCommon = <T,>({
/> />
</> </>
)} )}
{slider && isDot && ( {/* {slider && isDot && (
<div className="dots"> <div className="dots">
{dotArr.map((index) => { {dotArr.map((index) => {
return ( return (
@@ -99,9 +101,16 @@ const CarouselCommon = <T,>({
) )
})} })}
</div> </div>
)} )} */}
</div> </div>
) )
} }
const CarouselButtonGroup = ({ next, previous }: ButtonGroupProps) => {
return (
<>
<CustomCarouselArrow side="left" onClick={previous} />
<CustomCarouselArrow side="right" onClick={next} />
</>
)
}
export default CarouselCommon export default CarouselCommon

View File

@@ -2,24 +2,30 @@ import classNames from 'classnames'
import React from 'react' import React from 'react'
import ArrowLeft from 'src/components/icons/ArrowLeft' import ArrowLeft from 'src/components/icons/ArrowLeft'
import ArrowRight from 'src/components/icons/ArrowRight' import ArrowRight from 'src/components/icons/ArrowRight'
import "./CustomCarouselArrow.module.scss" import './CustomCarouselArrow.module.scss'
import { ArrowProps } from 'react-multi-carousel/lib/types'
interface CustomCarouselArrowProps interface CustomCarouselArrowProps extends ArrowProps {
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
side: 'left' | 'right' side: 'left' | 'right'
isDisabled?:Boolean isDisabled?: Boolean
} }
export const CustomCarouselArrow = ({ export const CustomCarouselArrow = ({
side,isDisabled, side,
...props isDisabled,
onClick,
}: CustomCarouselArrowProps) => { }: CustomCarouselArrowProps) => {
const handleClick = () => {
onClick && onClick()
}
return ( return (
<button <button
{...props} onClick={handleClick}
className={classNames("customArrow", { [`${side}Arrow`]: side,"isDisabledArrow":isDisabled})} className={classNames('customArrow', {
[`${side}Arrow`]: side,
isDisabledArrow: isDisabled,
})}
> >
{side==='left'?(<ArrowLeft/>):(<ArrowRight/>)} {side === 'left' ? <ArrowLeft /> : <ArrowRight />}
</button> </button>
) )
} }

View File

@@ -1,29 +1,30 @@
import { TOptionsEvents } from 'keen-slider';
import React from 'react'; import React from 'react';
import { ResponsiveType } from 'react-multi-carousel';
import { CarouselCommon, ViewAllItem } from 'src/components/common'; import { CarouselCommon, ViewAllItem } from 'src/components/common';
import ProductCard, { ProductCardProps } from 'src/components/common/ProductCard/ProductCard'; import ProductCard, { ProductCardProps } from 'src/components/common/ProductCard/ProductCard';
import { ROUTE } from 'src/utils/constanst.utils'; import { ROUTE } from 'src/utils/constanst.utils';
import { PRODUCT_DATA_TEST } from 'src/utils/demo-data'; import { PRODUCT_DATA_TEST } from 'src/utils/demo-data';
import s from './CartRecommendation.module.scss'; import s from './CartRecommendation.module.scss';
const option: TOptionsEvents = { const RESPONSIVE:ResponsiveType = {
slidesPerView: 1.5, desktop: {
mode: 'free', breakpoint: { max: 99999, min: 1440 },
breakpoints: { items: 2.5,
'(min-width: 640px)': { slidesToSlide: 1 // optional, default to 1.
slidesPerView: 1.5,
},
'(min-width: 768px)': {
slidesPerView: 2.5,
},
'(min-width: 1008px)': {
slidesPerView: 2.2,
},
'(min-width: 1440px)': {
slidesPerView: 2.5,
}
}, },
} lap: {
breakpoint: { max: 1440, min: 1008 },
items: 2.2,
},
tablet: {
breakpoint: { max: 1008, min: 768 },
items: 2.5,
},
mobile: {
breakpoint: { max: 768, min: 0 },
items: 1.5,
}
};
const CartRecommendation = () => { const CartRecommendation = () => {
return ( return (
@@ -39,7 +40,7 @@ const CartRecommendation = () => {
data={PRODUCT_DATA_TEST} data={PRODUCT_DATA_TEST}
Component={ProductCard} Component={ProductCard}
itemKey="cart-recommendation" itemKey="cart-recommendation"
option={option} responsive={RESPONSIVE}
defaultComponentProps={{ isSingleButton: true }} defaultComponentProps={{ isSingleButton: true }}
/> />
</div> </div>

View File

@@ -1,33 +1,63 @@
@import '../../../styles/utilities'; @import '../../../styles/utilities';
.featuredProductCardWarpper{ .featuredProductCardWarpper{
width: 59.8rem; // min-width: 30.2rem;
height: 28.8rem; height: 14.4rem;
padding: 2.4rem; padding: 2.4rem;
@apply bg-primary-light inline-flex justify-start items-center shape-common; @apply bg-primary-light inline-flex justify-start items-center shape-common ;
@screen md {
// min-width: 598px;
height: 28.8rem;
padding: 1.6rem 3.2rem 1.6rem 1.6rem;
}
@screen 2xl {
// min-width: 598px;
height: 28.8rem;
padding: 2.4rem 4rem 2.4rem 2.4rem;
}
.left{ .left{
width: 24rem; width: 10rem;
height: 24rem; height: 10rem;
@screen md {
width: 24rem;
height: 24rem;
}
} }
.right{ .right{
padding-left: 2.4rem; margin-left: 1.2rem;
min-width: 27rem; // min-width: 27rem;
max-width: 28.6rem; max-width: 16.6rem;
min-height: 16.8rem; max-height: 10rem;
@apply flex justify-between flex-col; @apply flex justify-between flex-col;
@screen md {
margin-left: 2.4rem;
max-width: 27.0rem;
min-height: 16.8rem;
}
.rightTop{ .rightTop{
min-height: 9.6rem; min-height: 6rem;
@screen md {
min-height: 9.6rem;
}
@apply flex justify-between flex-col; @apply flex justify-between flex-col;
.title{ .title{
@apply font-bold; @apply font-bold;
font-size: 2rem; font-size: 1.2rem;
line-height: 2.8rem; line-height: 1.6rem;
letter-spacing: -0.01em; letter-spacing: -0.01em;
color: var(--text-active); color: var(--text-active);
@screen md {
font-size: 2rem;
line-height: 2.8rem;
}
} }
.subTitle{ .subTitle{
color: var(--text-base); color: var(--text-base);
font-size: 1.6rem; font-size: 1.2rem;
line-height: 2.4rem; line-height: 1.6rem;
@screen md {
font-size: 1.6rem;
line-height: 2.4rem;
}
} }
.priceWrapper{ .priceWrapper{
@apply flex justify-start sm-headline; @apply flex justify-start sm-headline;

View File

@@ -5,7 +5,7 @@ import { LANGUAGE } from '../../../utils/language.utils'
import ButtonIconBuy from '../ButtonIconBuy/ButtonIconBuy' import ButtonIconBuy from '../ButtonIconBuy/ButtonIconBuy'
import ButtonCommon from '../ButtonCommon/ButtonCommon' import ButtonCommon from '../ButtonCommon/ButtonCommon'
import { ImgWithLink } from '..' import { ImgWithLink } from '..'
interface FeaturedProductCardProps extends FeaturedProductProps { export interface FeaturedProductCardProps extends FeaturedProductProps {
buttonText?: string buttonText?: string
} }

View File

@@ -6,7 +6,7 @@ import { ButtonCommon } from 'src/components/common'
import InputSearch from 'src/components/common/InputSearch/InputSearch' import InputSearch from 'src/components/common/InputSearch/InputSearch'
import MenuDropdown from 'src/components/common/MenuDropdown/MenuDropdown' import MenuDropdown from 'src/components/common/MenuDropdown/MenuDropdown'
import { IconBuy, IconFilter, IconHeart, IconHistory, IconUser } from 'src/components/icons' import { IconBuy, IconFilter, IconHeart, IconHistory, IconUser } from 'src/components/icons'
import { ACCOUNT_TAB, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils' import { ACCOUNT_TAB, FILTER_PAGE, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils'
import Logo from '../../../Logo/Logo' import Logo from '../../../Logo/Logo'
import s from './HeaderMenu.module.scss' import s from './HeaderMenu.module.scss'
interface Props { interface Props {
@@ -20,7 +20,6 @@ interface Props {
toggleCart: () => void, toggleCart: () => void,
} }
const FILTER_PAGE = [ROUTE.HOME, ROUTE.PRODUCTS]
const HeaderMenu = memo(({ isFull, isStickyHeader, visibleFilter, openModalAuthen, openModalInfo, toggleFilter, toggleCart }: Props) => { const HeaderMenu = memo(({ isFull, isStickyHeader, visibleFilter, openModalAuthen, openModalInfo, toggleFilter, toggleCart }: Props) => {
const router = useRouter() const router = useRouter()
@@ -113,16 +112,6 @@ const HeaderMenu = memo(({ isFull, isStickyHeader, visibleFilter, openModalAuthe
<IconBuy /> <IconBuy />
</button> </button>
</li> </li>
{
FILTER_PAGE.includes(router.pathname) && (
<li className={s.iconFilterDesk}>
<button className={s.iconFilter} onClick={toggleFilter}>
<IconFilter />
</button>
</li>
)
}
</ul> </ul>
</section> </section>
) )

View File

@@ -17,6 +17,7 @@ const ImgWithLink = ({ src, alt, blurDataURL = BLUR_DATA_IMG }: ImgWithLinkProps
className={s.imgWithLink} className={s.imgWithLink}
placeholder="blur" placeholder="blur"
blurDataURL={blurDataURL} blurDataURL={blurDataURL}
draggable='false'
/> />
</div> </div>
) )

View File

@@ -2,7 +2,7 @@ import { CommerceProvider } from '@framework'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { FC } from 'react' import { FC } from 'react'
import { useModalCommon } from 'src/components/hooks' import { useModalCommon } from 'src/components/hooks'
import { BRAND, CATEGORY, FEATURED, ROUTE } from 'src/utils/constanst.utils' import { BRAND, CATEGORY, FEATURED, FILTER_PAGE, ROUTE } from 'src/utils/constanst.utils'
import { ScrollToTop } from '..' import { ScrollToTop } from '..'
import Footer from '../Footer/Footer' import Footer from '../Footer/Footer'
import Header from '../Header/Header' import Header from '../Header/Header'
@@ -16,7 +16,7 @@ interface Props {
// note: demo code // note: demo code
const Layout: FC<Props> = ({ children }) => { const Layout: FC<Props> = ({ children }) => {
const { locale = 'en-US' } = useRouter() const { locale = 'en-US', pathname } = useRouter()
const { visible: visibleFilter, openModal: openFilter, closeModal: closeFilter } = useModalCommon({ initialValue: false }) const { visible: visibleFilter, openModal: openFilter, closeModal: closeFilter } = useModalCommon({ initialValue: false })
const router = useRouter() const router = useRouter()
@@ -42,6 +42,9 @@ const Layout: FC<Props> = ({ children }) => {
} }
<div className={s.filter}><MenuNavigationProductList categories={CATEGORY} brands={BRAND} featured={FEATURED} visible={visibleFilter} onClose={closeFilter} /> </div> <div className={s.filter}><MenuNavigationProductList categories={CATEGORY} brands={BRAND} featured={FEATURED} visible={visibleFilter} onClose={closeFilter} /> </div>
<ScrollToTop visibilityHeight={1500} /> <ScrollToTop visibilityHeight={1500} />
{
FILTER_PAGE.includes(pathname) && (<div className={s.filter}><MenuNavigationProductList categories={CATEGORY} brands={BRAND} featured={FEATURED} visible={visibleFilter} onClose={closeFilter}/> </div>)
}
<Footer /> <Footer />
</div> </div>
</CommerceProvider> </CommerceProvider>

View File

@@ -9,6 +9,7 @@
} }
} }
@screen lg { @screen lg {
max-width: 18.1rem;
@apply block; @apply block;
margin-right: 4rem; margin-right: 4rem;
padding: 0; padding: 0;

View File

@@ -20,13 +20,19 @@
} }
.productsWrap { .productsWrap {
@apply spacing-horizontal-left; @apply spacing-horizontal-left;
overflow: hidden;
@screen lg { @screen lg {
max-width: 75%; flex: 1;
// max-width: 75%;
padding: 0 0.8rem; padding: 0 0.8rem;
> div > div { > div > div {
@apply shape-common-lg bg-white; @apply shape-common-lg bg-white;
padding: 4rem 0; padding: 4rem 0;
} }
> div {
margin: 0 2.4;
overflow: visible
}
:global(.customArrow) { :global(.customArrow) {
@screen lg { @screen lg {
&:global(.leftArrow) { &:global(.leftArrow) {
@@ -40,7 +46,7 @@
} }
@screen xl { @screen xl {
padding: 0 2.4rem; padding: 0 2.4rem;
max-width: 80%; // max-width: 80%;
} }
} }
} }

View File

@@ -1,6 +1,6 @@
import classNames from 'classnames'; import classNames from 'classnames';
import { TOptionsEvents } from 'keen-slider';
import React from 'react'; import React from 'react';
import { ResponsiveType } from 'react-multi-carousel';
import CarouselCommon from '../CarouselCommon/CarouselCommon'; import CarouselCommon from '../CarouselCommon/CarouselCommon';
import ProductCard, { ProductCardProps } from '../ProductCard/ProductCard'; import ProductCard, { ProductCardProps } from '../ProductCard/ProductCard';
import InfoProducts from './InfoProducts/InfoProducts'; import InfoProducts from './InfoProducts/InfoProducts';
@@ -12,31 +12,36 @@ interface Props {
subtitle?: string, subtitle?: string,
hasBorderBottomMobile?: boolean, hasBorderBottomMobile?: boolean,
} }
const OPTION_DEFAULT: TOptionsEvents = {
slidesPerView: 2,
mode: 'free',
breakpoints: {
'(min-width: 640px)': {
slidesPerView: 3,
},
'(min-width: 768px)': {
slidesPerView: 3,
},
'(min-width: 1008px)': {
slidesPerView: 3.5,
},
'(min-width: 1024px)': {
slidesPerView: 2.5,
},
'(min-width: 1280px)': {
slidesPerView: 3.5,
},
'(min-width: 1440px)': {
slidesPerView: 4.5,
},
},
}
const RESPONSIVE:ResponsiveType = {
xxl: {
breakpoint: { max: 9999, min: 1440 },
items: 4.5,
slidesToSlide: 1 // optional, default to 1.
},
lg: {
breakpoint: { max: 1440, min: 1280 },
items: 3.5,
slidesToSlide: 1 // optional, default to 1.
},
desktop: {
breakpoint: { max: 1280, min: 1024 },
items: 2.5,
slidesToSlide: 1 // optional, default to 1.
},
lap: {
breakpoint: { max: 1024, min: 1008 },
items: 3.5,
},
tablet: {
breakpoint: { max: 1008, min: 640 },
items: 3,
},
mobile: {
breakpoint: { max: 640, min: 0 },
items: 2,
}
};
const ListProductWithInfo = ({ data, title, subtitle, hasBorderBottomMobile }: Props) => { const ListProductWithInfo = ({ data, title, subtitle, hasBorderBottomMobile }: Props) => {
return ( return (
<div className={classNames({ <div className={classNames({
@@ -51,8 +56,9 @@ const ListProductWithInfo = ({ data, title, subtitle, hasBorderBottomMobile }: P
<CarouselCommon<ProductCardProps> <CarouselCommon<ProductCardProps>
data={data} data={data}
Component={ProductCard} Component={ProductCard}
// draggable={true} infinite={true}
itemKey={title} itemKey={title}
option={OPTION_DEFAULT} responsive={RESPONSIVE}
/> />
</div> </div>
</div> </div>

View File

@@ -3,6 +3,9 @@
min-height: 31.8rem; min-height: 31.8rem;
padding: 1.2rem 1.2rem 0 1.2rem; padding: 1.2rem 1.2rem 0 1.2rem;
margin: auto; margin: auto;
@screen md {
margin: 0;
}
margin-bottom: 1px; margin-bottom: 1px;
@apply flex flex-col justify-between; @apply flex flex-col justify-between;
&.notSell { &.notSell {

View File

@@ -32,7 +32,6 @@ const ProductCard = ({
</div> </div>
} }
return ( return (
<div className={s.productCardWarpper}> <div className={s.productCardWarpper}>
<div className={s.cardTop}> <div className={s.cardTop}>

View File

@@ -1,4 +1,3 @@
import { TOptionsEvents } from 'keen-slider'
import React from 'react' import React from 'react'
import CarouselCommon, { import CarouselCommon, {
CarouselCommonProps, CarouselCommonProps,
@@ -8,38 +7,42 @@ import s from "./ProductCarousel.module.scss"
interface ProductCarouselProps interface ProductCarouselProps
extends Omit<CarouselCommonProps<ProductCardProps>, 'Component' | "option"> { extends Omit<CarouselCommonProps<ProductCardProps>, 'Component' | "option"> {
option?: TOptionsEvents
} }
const RESPONSIVE = {
const OPTION_DEFAULT: TOptionsEvents = { lgScreen: {
slidesPerView: 2, breakpoint: { max:9999, min: 1440 },
mode: 'free', items: 5.5,
breakpoints: { slidesToSlide: 1 // optional, default to 1.
'(min-width: 640px)': {
slidesPerView: 3,
},
'(min-width: 768px)': {
slidesPerView: 3,
},
'(min-width: 1008px)': {
slidesPerView: 3.5,
},
'(min-width: 1280px)': {
slidesPerView: 4.5,
},
'(min-width: 1440px)': {
slidesPerView: 5.5,
},
}, },
} desktop: {
const ProductCarousel = ({ option, data, ...props }: ProductCarouselProps) => { breakpoint: { max: 1440, min: 1280 },
items: 4.5,
slidesToSlide: 1 // optional, default to 1.
},
lap: {
breakpoint: { max: 1280, min: 1008 },
items: 3.5,
slidesToSlide: 1 // optional, default to 1.
},
tablet: {
breakpoint: { max: 1008, min: 640 },
items: 3,
},
mobile: {
breakpoint: { max: 640, min: 0 },
items: 2,
}
};
const ProductCarousel = ({ data, responsive= RESPONSIVE, ...props }: ProductCarouselProps) => {
return ( return (
<div className={s.productCardWarpper}> <div className={s.productCardWarpper}>
<CarouselCommon<ProductCardProps> <CarouselCommon<ProductCardProps>
data={data} data={data}
Component={ProductCard} Component={ProductCard}
draggable={true} infinite={true}
responsive={responsive}
isPadding
{...props} {...props}
option={{ ...OPTION_DEFAULT, ...option }}
/> />
</div> </div>
) )

View File

@@ -1,9 +1,8 @@
@import '../../../styles/utilities'; @import '../../../styles/utilities';
.quanittyInputWarper { .quanittyInputWarper {
@apply shape-common-border; @apply shape-common-border;
padding: 0.5px 0;
&::before{ &::before{
height: 100%;
top: 1px;
background-color: var(--text-active); background-color: var(--text-active);
} }
.inner { .inner {

View File

@@ -1,43 +1,47 @@
import { TOptionsEvents } from 'keen-slider'
import React from 'react' import React from 'react'
import { ResponsiveType } from 'react-multi-carousel'
import CarouselCommon, { import CarouselCommon, {
CarouselCommonProps, CarouselCommonProps,
} from '../CarouselCommon/CarouselCommon' } from '../CarouselCommon/CarouselCommon'
import RecipeCard, { RecipeCardProps } from '../RecipeCard/RecipeCard' import RecipeCard, { RecipeCardProps } from '../RecipeCard/RecipeCard'
import s from "./RecipeCarousel.module.scss" import s from './RecipeCarousel.module.scss'
interface RecipeCarouselProps interface RecipeCarouselProps
extends Omit<CarouselCommonProps<RecipeCardProps>, 'Component'|"option"> { extends Omit<CarouselCommonProps<RecipeCardProps>, 'Component' | 'option'> {}
option?:TOptionsEvents
}
const OPTION_DEFAULT: TOptionsEvents = { const RESPONSIVE: ResponsiveType = {
slidesPerView: 1.25, largeDesktop: {
mode: 'free', breakpoint: { max: 9999, min: 1536 },
spacing:24, items: 3.5,
breakpoints: { slidesToSlide: 1, // optional, default to 1.
'(min-width: 640px)': { },
slidesPerView: 2, desktop: {
}, breakpoint: { max: 1536, min: 1440 },
'(min-width: 1024px)': { items: 3,
slidesPerView: 2.5, slidesToSlide: 1, // optional, default to 1.
}, },
'(min-width: 1440px)': { lap: {
slidesPerView: 3, breakpoint: { max: 1440, min: 1024 },
}, items: 2.5,
'(min-width: 1536px)': { },
slidesPerView: 3.5, tablet: {
}, breakpoint: { max: 1024, min: 640 },
items: 2,
},
mobile: {
breakpoint: { max: 640, min: 0 },
items: 1.25,
}, },
} }
const RecipeCarousel = ({ option, data, ...props }: RecipeCarouselProps) => { const RecipeCarousel = ({ data, ...props }: RecipeCarouselProps) => {
return ( return (
<div className={s.recipeCardWarpper}> <div className={s.recipeCardWarpper}>
<CarouselCommon<RecipeCardProps> <CarouselCommon<RecipeCardProps>
data={data} data={data}
Component={RecipeCard} Component={RecipeCard}
{...props} {...props}
option={{ ...OPTION_DEFAULT, ...option }} // option={{ ...OPTION_DEFAULT, ...option }}
responsive={RESPONSIVE}
/> />
</div> </div>
) )

View File

@@ -1,30 +1,34 @@
import { TOptionsEvents } from 'keen-slider';
import React from 'react'; import React from 'react';
import { ResponsiveType } from 'react-multi-carousel';
import { CarouselCommon, HeadingCommon, RecipeCard, ViewAllItem } from 'src/components/common'; import { CarouselCommon, HeadingCommon, RecipeCard, ViewAllItem } from 'src/components/common';
import { RecipeCardProps } from 'src/components/common/RecipeCard/RecipeCard'; import { RecipeCardProps } from 'src/components/common/RecipeCard/RecipeCard';
import { ROUTE } from 'src/utils/constanst.utils'; import { ROUTE } from 'src/utils/constanst.utils';
import s from './RecommendedRecipes.module.scss'; import s from './RecommendedRecipes.module.scss';
const OPTION_DEFAULT: TOptionsEvents = { const RESPONSIVE: ResponsiveType = {
slidesPerView: 1.25, largeDesktop: {
mode: 'free', breakpoint: { max: 9999, min: 1536 },
spacing: 24, items: 3.5,
breakpoints: { slidesToSlide: 1, // optional, default to 1.
'(min-width: 640px)': {
slidesPerView: 2,
},
'(min-width: 1024px)': {
slidesPerView: 2.5,
},
'(min-width: 1440px)': {
slidesPerView: 3,
},
'(min-width: 1536px)': {
slidesPerView: 3.5,
},
}, },
} desktop: {
breakpoint: { max: 1536, min: 1440 },
items: 3,
slidesToSlide: 1, // optional, default to 1.
},
lap: {
breakpoint: { max: 1440, min: 1024 },
items: 2.5,
},
tablet: {
breakpoint: { max: 1024, min: 640 },
items: 2,
},
mobile: {
breakpoint: { max: 640, min: 0 },
items: 1.25,
},
}
interface Props { interface Props {
data: RecipeCardProps[], data: RecipeCardProps[],
} }
@@ -41,7 +45,7 @@ const RecommendedRecipes = ({ data }: Props) => {
data={data} data={data}
Component={RecipeCard} Component={RecipeCard}
itemKey="Recommended Recipes" itemKey="Recommended Recipes"
option={OPTION_DEFAULT} responsive={RESPONSIVE}
/> />
</div> </div>
</div> </div>

View File

@@ -1,43 +1,47 @@
import { TOptionsEvents } from 'keen-slider'
import React from 'react' import React from 'react'
import CarouselCommon, { import CarouselCommon, {
CarouselCommonProps, CarouselCommonProps,
} from '../../CarouselCommon/CarouselCommon' } from '../../CarouselCommon/CarouselCommon'
import BlogCard, { BlogCardProps } from 'src/components/common/CardBlog/CardBlog' import BlogCard, { BlogCardProps } from 'src/components/common/CardBlog/CardBlog'
import s from "./BlogPostCarousel.module.scss" import s from "./BlogPostCarousel.module.scss"
import { ResponsiveType } from 'react-multi-carousel'
interface BlogPostCarouselProps interface BlogPostCarouselProps
extends Omit<CarouselCommonProps<BlogCardProps>, 'Component'|"option"> { extends Omit<CarouselCommonProps<BlogCardProps>, 'Component'|"option"> {
option?:TOptionsEvents
} }
const OPTION_DEFAULT: TOptionsEvents = { const RESPONSIVE: ResponsiveType = {
slidesPerView: 1.25, largeDesktop: {
mode: 'free', breakpoint: { max: 9999, min: 1536 },
spacing:24, items: 3.5,
breakpoints: { slidesToSlide: 1, // optional, default to 1.
'(min-width: 640px)': { },
slidesPerView: 2, desktop: {
}, breakpoint: { max: 1536, min: 1440 },
'(min-width: 1024px)': { items: 3,
slidesPerView: 2.5, slidesToSlide: 1, // optional, default to 1.
}, },
'(min-width: 1440px)': { lap: {
slidesPerView: 3, breakpoint: { max: 1440, min: 1024 },
}, items: 2.5,
'(min-width: 1536px)': { },
slidesPerView: 3.5, tablet: {
}, breakpoint: { max: 1024, min: 640 },
items: 2,
},
mobile: {
breakpoint: { max: 640, min: 0 },
items: 1.25,
}, },
} }
const BlogPostCarousel = ({ option, data, ...props }: BlogPostCarouselProps) => { const BlogPostCarousel = ({ data, ...props }: BlogPostCarouselProps) => {
return ( return (
<div className={s.blogCardWarpper}> <div className={s.blogCardWarpper}>
<CarouselCommon<BlogCardProps> <CarouselCommon<BlogCardProps>
data={data} data={data}
Component={BlogCard} Component={BlogCard}
{...props} {...props}
option={{ ...OPTION_DEFAULT, ...option }} responsive={RESPONSIVE}
/> />
</div> </div>
) )

View File

@@ -0,0 +1,16 @@
@import '../../../../styles/utilities';
.warpper {
@apply spacing-horizontal;
@screen xl {
:global(.customArrow) {
@screen lg {
&:global(.leftArrow) {
left: calc(-6.4rem - 2rem);
}
&:global(.rightArrow) {
right: calc(-6.4rem - 2rem);
}
}
}
}
}

View File

@@ -0,0 +1,89 @@
import React from 'react'
import { ResponsiveType } from 'react-multi-carousel'
import { CarouselCommon, FeaturedProductCard } from 'src/components/common'
import { FeaturedProductCardProps } from 'src/components/common/FeaturedProductCard/FeaturedProductCard'
import s from "./FeaturedProductsCarousel.module.scss"
interface FeaturedProductsCarouselProps {
}
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 },
items: 2.25,
slidesToSlide: 1, // optional, default to 1.
},
largeScreen: {
breakpoint: { max: 1500, min: 1440 },
items: 2.075,
slidesToSlide: 1, // optional, default to 1.
},
largeDesktop: {
breakpoint: { max: 1440, min: 1280 },
items: 1.75,
slidesToSlide: 1, // optional, default to 1.
},
desktop: {
breakpoint: { max: 1280, min: 1148 },
items: 1.5,
slidesToSlide: 1, // optional, default to 1.
},
smallDesktop: {
breakpoint: { max: 1148, min: 1024 },
items: 1.375,
slidesToSlide: 1, // optional, default to 1.
},
lap: {
breakpoint: { max: 1024, min: 968 },
items: 1.75,
},
tablet: {
breakpoint: { max: 968, min: 768 },
items: 1.075,
},
smallTablet: {
breakpoint: { max: 768, min: 640 },
items: 1.25,
},
largeMobile: {
breakpoint: { max: 640, min: 400 },
items: 2,
},
mobile: {
breakpoint: { max: 400, min: 300 },
items: 1.5,
},
smallMobile: {
breakpoint: { max: 300, min: 0 },
items: 1,
},
}
const FeaturedProductsCarousel = ({}: FeaturedProductsCarouselProps) => {
return (
<div className={s.warpper}>
<CarouselCommon<FeaturedProductCardProps> data={dataDemo} Component={FeaturedProductCard} itemKey="featured-products" responsive={RESPONSIVE}/>
</div>
)
}
export default FeaturedProductsCarousel

View File

@@ -1,15 +1,21 @@
@import "../../../../styles/utilities"; @import "../../../../styles/utilities";
.homeBanner { .homeBanner {
@apply spacing-horizontal; @apply spacing-horizontal overflow-hidden;
margin-bottom: 2.8rem; margin-bottom: 2.8rem;
.left { .left {
@apply hidden; @apply hidden;
margin-bottom: 3rem; margin-bottom: 3rem;
max-width: 50rem;
} }
@screen xl { @screen xl {
@apply grid; @apply grid;
grid-template-columns: 1fr 1.8fr; grid-template-columns: 35.75% 64.25%;
// grid-template-columns: 1fr 1.8fr;
> div {
@apply w-full overflow-hidden;
}
.left { .left {
@apply relative flex items-end justify-center shape-common-lg; @apply relative flex items-end justify-center shape-common-lg;
margin-right: 1.6rem; margin-right: 1.6rem;
@@ -29,7 +35,6 @@
@apply relative font-heading text-center; @apply relative font-heading text-center;
padding: 2.4rem 2.4rem 4.8rem; padding: 2.4rem 2.4rem 4.8rem;
width: min-content; width: min-content;
color: var(--white); color: var(--white);
font-size: 8.8rem; font-size: 8.8rem;
line-height: 8rem; line-height: 8rem;

View File

@@ -1,44 +1,49 @@
import React from 'react' import React from 'react'
import { TOptionsEvents } from 'keen-slider'
import HomeFeatureItem, {HomeFeatureItemProps} from '../HomeFeatureItem/HomeFeatureItem' import HomeFeatureItem, {HomeFeatureItemProps} from '../HomeFeatureItem/HomeFeatureItem'
import CarouselCommon, {CarouselCommonProps} from '../../../../../common/CarouselCommon/CarouselCommon' import CarouselCommon, {CarouselCommonProps} from '../../../../../common/CarouselCommon/CarouselCommon'
import { ResponsiveType } from 'react-multi-carousel'
interface HomeFeatureCarouselProps interface HomeFeatureCarouselProps
extends Omit<CarouselCommonProps<HomeFeatureItemProps>, 'Component' | "option"> { extends Omit<CarouselCommonProps<HomeFeatureItemProps>, 'Component' | "option"> {
option?: TOptionsEvents
} }
const OPTION_DEFAULT: TOptionsEvents = { const RESPONSIVE: ResponsiveType = {
slidesPerView: 1.2, largeDesktop: {
mode: 'free', breakpoint: { max: 9999, min: 1440 },
breakpoints: { items: 3,
'(min-width: 640px)': { slidesToSlide: 1, // optional, default to 1.
slidesPerView: 1.8, },
}, desktop: {
'(min-width: 768px)': { breakpoint: { max: 1440, min: 1280 },
slidesPerView: 2.1, items: 2.8,
}, slidesToSlide: 1, // optional, default to 1.
'(min-width: 1008px)': { },
slidesPerView: 2.3, smallDesktop: {
}, breakpoint: { max: 1280, min: 1008 },
'(min-width: 1280px)': { items: 2.3,
slidesPerView: 2.8, slidesToSlide: 1, // optional, default to 1.
}, },
'(min-width: 1440px)': { lap: {
slidesPerView: 3, breakpoint: { max: 1008, min: 768 },
}, items: 2.1,
},
tablet: {
breakpoint: { max: 768, min: 640 },
items: 1.8,
},
mobile: {
breakpoint: { max: 640, min: 0 },
items: 1.2,
}, },
} }
const HomeFeatureCarousel = ({data, ...props} : HomeFeatureCarouselProps) => {
const HomeFeatureCarousel = ({option, data, ...props} : HomeFeatureCarouselProps) => {
return ( return (
<div> <div>
<CarouselCommon<HomeFeatureItemProps> <CarouselCommon<HomeFeatureItemProps>
data={data} data={data}
Component={HomeFeatureItem} Component={HomeFeatureItem}
{...props} {...props}
option={{ ...OPTION_DEFAULT, ...option }} responsive={RESPONSIVE}
/> />
</div> </div>
) )

View File

@@ -6,4 +6,5 @@ export { default as HomeSubscribe } from './HomeSubscribe/HomeSubscribe'
export { default as HomeVideo } from './HomeVideo/HomeVideo' export { default as HomeVideo } from './HomeVideo/HomeVideo'
export { default as HomeCollection } from './HomeCollection/HomeCollection' export { default as HomeCollection } from './HomeCollection/HomeCollection'
export { default as HomeRecipe } from './HomeRecipe/HomeRecipe' export { default as HomeRecipe } from './HomeRecipe/HomeRecipe'
export { default as FeaturedProductsCarousel } from './FeaturedProductsCarousel/FeaturedProductsCarousel'
export { default as HomeFeature } from './HomeFeature/HomeFeature' export { default as HomeFeature } from './HomeFeature/HomeFeature'

View File

@@ -8,5 +8,9 @@
} }
> div { > div {
width: 100%; width: 100%;
// > div {
// height: 100%;
// }
} }
} }

View File

@@ -1,4 +1,5 @@
import React from 'react' import React from 'react'
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 s from './ProductImgs.module.scss' import s from './ProductImgs.module.scss'
@@ -23,10 +24,13 @@ const DATA = [
} }
] ]
const option = { const RESPONSIVE: ResponsiveType = {
slidesPerView: 1, desktop: {
} breakpoint: { max: 9999, min: 0 },
items: 1,
slidesToSlide: 1, // optional, default to 1.
},
}
const ProductImgs = ({ }: Props) => { const ProductImgs = ({ }: Props) => {
return ( return (
<section className={s.productImgs}> <section className={s.productImgs}>
@@ -34,8 +38,8 @@ const ProductImgs = ({ }: Props) => {
data={DATA} data={DATA}
itemKey="product-detail-img" itemKey="product-detail-img"
Component={ProductImgItem} Component={ProductImgItem}
option={option} responsive={RESPONSIVE}
isDot={true} showDots={true}
/> />
</section > </section >
) )

View File

@@ -16,6 +16,12 @@ const ProductListBanner = ({ }: Props) => {
subtitle: "Last call! Shop deep deals on 100+ bulk picks while you can.", subtitle: "Last call! Shop deep deals on 100+ bulk picks while you can.",
imgLink: BannerRight.src, imgLink: BannerRight.src,
size: "large", size: "large",
},
{
title: "Save 15% on your first order",
subtitle: "Last call! Shop deep deals on 100+ bulk picks while you can.",
imgLink: BannerRight.src,
size: "large",
} }
] ]
} }

View File

@@ -14,9 +14,10 @@
@apply flex; @apply flex;
} }
.categories{ .categories{
padding-right: 2.4rem;
@apply hidden; @apply hidden;
@screen md { @screen md {
@apply hidden; @apply block;
} }
@screen xl{ @screen xl{
@apply block; @apply block;

View File

@@ -1,4 +1,4 @@
@import url("https://fonts.googleapis.com/css2?family=Nunito&family=Poppins:wght@500&family=Righteous&display=swap"); @import url("https://fonts.googleapis.com/css2?family=Nunito&family=Poppins:wght@500&display=swap");
@import '../../public/fonts/style.css'; @import '../../public/fonts/style.css';
:root { :root {
@@ -42,7 +42,7 @@
--line-height: 2.4rem; --line-height: 2.4rem;
--font-sans: "Nunito", -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "Helvetica", sans-serif; --font-sans: "Nunito", -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "Helvetica", sans-serif;
--font-heading: "Norquay-bold", "Righteous", -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "Helvetica", sans-serif; --font-heading: "Norquay-bold", monospace, -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "Helvetica", sans-serif;
--font-logo: "Poppins", -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "Helvetica", sans-serif; --font-logo: "Poppins", -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "Helvetica", sans-serif;
} }

View File

@@ -125,6 +125,8 @@ export const FEATURED = [
export const DEFAULT_BLOG_PAGE_SIZE=6; export const DEFAULT_BLOG_PAGE_SIZE=6;
export const FILTER_PAGE = [ROUTE.HOME,ROUTE.PRODUCTS]
export const STATE_OPTIONS = [ export const STATE_OPTIONS = [
{ {
name: 'Hồ Chí Minh', name: 'Hồ Chí Minh',
@@ -134,4 +136,4 @@ export const STATE_OPTIONS = [
name: 'Hà Nội', name: 'Hà Nội',
value: 'Hà Nội', value: 'Hà Nội',
}, },
] ]

2435
yarn.lock

File diff suppressed because it is too large Load Diff