mirror of
https://github.com/vercel/commerce.git
synced 2025-07-22 20:26:49 +00:00
Merge pull request #60 from KieIO/fixbug-13/9/2021-datnguyen
Refactor Carousel Common
This commit is contained in:
3
next-env.d.ts
vendored
3
next-env.d.ts
vendored
@@ -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.
|
||||||
|
@@ -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",
|
||||||
|
@@ -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';
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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 />
|
||||||
|
@@ -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/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,3 @@
|
|||||||
|
.bannerWrap {
|
||||||
|
@apply w-full;
|
||||||
|
}
|
@@ -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>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -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");
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
|
@@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -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>
|
||||||
|
@@ -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;
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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>
|
||||||
)
|
)
|
||||||
|
@@ -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>
|
||||||
)
|
)
|
||||||
|
@@ -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>
|
||||||
|
@@ -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;
|
||||||
|
@@ -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%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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>
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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}>
|
||||||
|
@@ -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>
|
||||||
)
|
)
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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>
|
||||||
)
|
)
|
||||||
|
@@ -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>
|
||||||
|
@@ -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>
|
||||||
)
|
)
|
||||||
|
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -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
|
@@ -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;
|
||||||
|
@@ -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>
|
||||||
)
|
)
|
||||||
|
@@ -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'
|
||||||
|
@@ -8,5 +8,9 @@
|
|||||||
}
|
}
|
||||||
> div {
|
> div {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
// > div {
|
||||||
|
// height: 100%;
|
||||||
|
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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 >
|
||||||
)
|
)
|
||||||
|
@@ -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",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
Reference in New Issue
Block a user