feat: product caroucel

:%s
This commit is contained in:
unknown 2021-08-25 13:41:45 +07:00
commit 7a5c5657fe
20 changed files with 320 additions and 136 deletions

View File

@ -1,27 +1,88 @@
import { Layout, ProductCard } from 'src/components/common' import { Layout, ProductCard } from 'src/components/common'
import {CarouselCommon } from 'src/components/common' import {CarouselCommon } from 'src/components/common'
import image1 from "../public/assets/images/image5.png" import ProductCaroucel from 'src/components/common/ProductCaroucel/ProductCaroucel'
import image5 from "../public/assets/images/image5.png"
import image6 from "../public/assets/images/image6.png"
import image7 from "../public/assets/images/image7.png"
import image8 from "../public/assets/images/image8.png"
const dataTest = [{ const dataTest = [{
text:1 name:"Tomato",
weight:"250g",
category:"VEGGIE",
price:"Rp 27.500",
imageSrc:image5.src
},{ },{
text:2 name:"Cucumber",
weight:"250g",
category:"VEGGIE",
price:"Rp 27.500",
imageSrc:image6.src
},{ },{
text:3 name:"Carrot",
weight:"250g",
category:"VEGGIE",
price:"Rp 27.500",
imageSrc:image7.src
},{ },{
text:4 name:"Salad",
weight:"250g",
category:"VEGGIE",
price:"Rp 27.500",
imageSrc:image8.src
},{ },{
text:5 name:"Tomato",
weight:"250g",
category:"VEGGIE",
price:"Rp 27.500",
imageSrc:image5.src
},{ },{
text:6 name:"Cucumber",
weight:"250g",
category:"VEGGIE",
price:"Rp 27.500",
imageSrc:image6.src
},{
name:"Tomato",
weight:"250g",
category:"VEGGIE",
price:"Rp 27.500",
imageSrc:image5.src
},{
name:"Cucumber",
weight:"250g",
category:"VEGGIE",
price:"Rp 27.500",
imageSrc:image6.src
},{
name:"Carrot",
weight:"250g",
category:"VEGGIE",
price:"Rp 27.500",
imageSrc:image7.src
},{
name:"Salad",
weight:"250g",
category:"VEGGIE",
price:"Rp 27.500",
imageSrc:image8.src
},{
name:"Tomato",
weight:"250g",
category:"VEGGIE",
price:"Rp 27.500",
imageSrc:image5.src
},{
name:"Cucumber",
weight:"250g",
category:"VEGGIE",
price:"Rp 27.500",
imageSrc:image6.src
}] }]
const test = (props:{text:string})=><div className="h-64 bg-yellow-300">{props.text}</div>
export default function Home() { export default function Home() {
return ( return (
<> <>
<CarouselCommon data={dataTest} Component={test} itemKey="test"/> <ProductCaroucel data={dataTest} itemKey="product-1" />
<ProductCard name="tomato" weight = "250g" category ="VEGGIE" price="Rp 27.500" imageSrc={image1.src}/>
</> </>
) )
} }

View File

@ -53,11 +53,11 @@
&.ghost { &.ghost {
@apply bg-white; @apply bg-white;
color: var(--primary); color: var(--text-active);
border: 1px solid var(--primary); border: 1px solid var(--text-active);
&.loading { &.loading {
&::before { &::before {
border-top-color: var(--primary); border-top-color: var(--text-active);
} }
} }
} }

View File

@ -1,5 +1,25 @@
.navigation_wrapper{ @import '../../../styles/utilities';
.navigationWrapper{
@apply relative; @apply relative;
min-height: theme("caroucel.arrow-height") ; min-height: theme("caroucel.arrow-height") ;
.isPadding{
@apply spacing-horizontal;
}
:global(.customArrow) {
width: 64px;
height: 64px;
&:focus{
outline: none;
}
@apply absolute top-1/2 bg-background-arrow transform -translate-y-1/2 flex justify-center items-center transition duration-100;
&:global(.leftArrow){
@apply left-0;
}
&:global(.rightArrow){
@apply right-0;
}
&:global(.isDisabledArrow){
@apply hidden ;
}
}
} }

View File

@ -1,21 +1,30 @@
import { useKeenSlider } from 'keen-slider/react' import { useKeenSlider } from 'keen-slider/react'
import React from 'react' import React from 'react'
import 'keen-slider/keen-slider.min.css' import 'keen-slider/keen-slider.min.css'
import { CustomCarouselArrow } from './CustomArrow/CustomCarouselArrow'; import { CustomCarouselArrow } from './CustomArrow/CustomCarouselArrow'
import s from "./CaroucelCommon.module.scss" import s from './CaroucelCommon.module.scss'
interface CarouselCommonProps { import { TOptionsEvents } from 'keen-slider'
children?: React.ReactNode import classNames from 'classnames'
data?: any[] export interface CarouselCommonProps<T> {
Component: React.ComponentType<any> data: T[]
isArrow?:Boolean Component: React.ComponentType<T>
itemKey:String isArrow?: Boolean
itemKey: String
option: TOptionsEvents
keenClassname?: string
isPadding?: boolean
} }
const CarouselCommon = ({ data, Component,itemKey }: CarouselCommonProps) => { const CarouselCommon = <T,>({
data,
Component,
itemKey,
keenClassname,isPadding=false,
option: { slideChanged, ...sliderOption },
}: CarouselCommonProps<T>) => {
const [currentSlide, setCurrentSlide] = React.useState(0) const [currentSlide, setCurrentSlide] = React.useState(0)
const [sliderRef, slider] = useKeenSlider<HTMLDivElement>({ const [sliderRef, slider] = useKeenSlider<HTMLDivElement>({
slidesPerView: 1, ...sliderOption,
initial: 0,
slideChanged(s) { slideChanged(s) {
setCurrentSlide(s.details().relativeSlide) setCurrentSlide(s.details().relativeSlide)
}, },
@ -28,28 +37,28 @@ const CarouselCommon = ({ data, Component,itemKey }: CarouselCommonProps) => {
slider.prev() slider.prev()
} }
return ( return (
<div className={s.navigation_wrapper}> <div className={s.navigationWrapper}>
<div ref={sliderRef} className="keen-slider"> <div ref={sliderRef} className={classNames('keen-slider', keenClassname,{[s.isPadding]:isPadding})}>
{data?.map((props,index) => ( {data?.map((props, index) => (
<div className="keen-slider__slide" key={`${itemKey}-${index}`}> <div className="keen-slider__slide" key={`${itemKey}-${index}`}>
<Component {...props} /> <Component {...props} />
</div> </div>
))} ))}
</div> </div>
{slider && ( {slider && (
<> <>
<CustomCarouselArrow <CustomCarouselArrow
side="right" side="right"
onClick={handleRightArrowClick} onClick={handleRightArrowClick}
isDisabled={currentSlide === slider.details().size - 1} // isDisabled={currentSlide === slider.details().size - 1}
/> />
<CustomCarouselArrow <CustomCarouselArrow
side="left" side="left"
onClick={handleLeftArrowClick} onClick={handleLeftArrowClick}
isDisabled={currentSlide === 0} // isDisabled={currentSlide === 0}
/> />
</> </>
)} )}
</div> </div>
) )
} }

View File

@ -1,17 +1,37 @@
.custom_arrow{ // .customArrow{
width: 64px; // width: 64px;
height: 64px; // height: 64px;
&: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;
&.left{ // &.leftArrow{
@apply left-0; // @apply left-0;
} // }
&.right{ // &.rightArrow{
@apply right-0; // @apply right-0;
} // }
&.isDisabled{ // &.isDisabled{
@apply hidden ; // @apply hidden ;
// }
// }
.navigationWrapper{
:global(.customArrow) {
width: 64px;
height: 64px;
&:focus{
outline: none;
}
@apply absolute top-1/2 bg-background-arrow transform -translate-y-1/2 flex justify-center items-center transition duration-100;
&.leftArrow{
@apply left-0;
}
&.rightArrow{
@apply right-0;
}
&.isDisabled{
@apply hidden ;
}
} }
} }

View File

@ -2,11 +2,13 @@ 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 s from "./CustomCarouselArrow.module.scss" import "./CustomCarouselArrow.module.scss"
// import s from "../CaroucelCommon.module.scss"
interface CustomCarouselArrowProps interface CustomCarouselArrowProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> { extends React.ButtonHTMLAttributes<HTMLButtonElement> {
side: 'left' | 'right' side: 'left' | 'right'
isDisabled:Boolean isDisabled?:Boolean
} }
export const CustomCarouselArrow = ({ export const CustomCarouselArrow = ({
@ -16,7 +18,8 @@ export const CustomCarouselArrow = ({
return ( return (
<button <button
{...props} {...props}
className={classNames(`${s.custom_arrow}`, { [`${s[side]}`]: side,[`${s.isDisabled}`]:isDisabled })} // className={classNames(`${s.customArrow}`, { [`${s[`${side}Arrow`]}`]: side,[`${s.isDisabled}`]:isDisabled })}
className={classNames("customArrow", { [`${side}Arrow`]: side,"isDisabledArrow":isDisabled})}
> >
{side==='left'?(<ArrowLeft/>):(<ArrowRight/>)} {side==='left'?(<ArrowLeft/>):(<ArrowRight/>)}
</button> </button>

View File

@ -2,9 +2,14 @@
.heartToggle{ .heartToggle{
cursor: pointer; cursor: pointer;
width: 4.8rem; width: 2.4rem;
height: 4.8rem; height: 2.4rem;
display: flex; path{
justify-content: center; stroke: theme("colors.primary");
align-items: center; }
}
.isToggleOn{
svg path{
stroke: theme("colors.primary");
}
} }

View File

@ -1,19 +1,27 @@
import { Heart } from '@components/icons' import classNames from 'classnames'
import React, { useState } from 'react' import IconHeart from 'src/components/icons/IconHeart'
import React, { memo } from 'react'
import s from './ItemWishList.module.scss' import s from './ItemWishList.module.scss'
interface Props { interface Props {
className?: string isActive?: boolean,
children?: any onClick?: () => void
onChange?: () => void
} }
const ItemWishList = ({}:Props) => { const ItemWishList = memo(({isActive, onClick, onChange}:Props) => {
const [isClick,setClick] = useState(false) const handleClick = () => {
isActive = !isActive
}
return( return(
<div className={s.heartToggle} onClick={() => setClick(!isClick)}> <div className={classNames({
<Heart color={isClick ? "#D1644D" : "#5B9A74"}/> [s.heartToggle]:true,
[s.isToggleOn]:isActive
})}
onClick={handleClick}>
<IconHeart />
</div> </div>
) )
} })
export default ItemWishList export default ItemWishList

View File

@ -1,6 +1,4 @@
@import '../../../styles/utilities'; @import '../../../styles/utilities';
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@700&display=swap');
.logo{ .logo{
display: flex; display: flex;
@ -12,7 +10,7 @@
margin-right: 1.2rem; margin-right: 1.2rem;
} }
.conTent{ .conTent{
font-family: 'Poppins', sans-serif; @apply font-logo;
text-transform: uppercase; text-transform: uppercase;
line-height: 3.2rem; line-height: 3.2rem;
letter-spacing: -0.02rem; letter-spacing: -0.02rem;

View File

@ -1,15 +1,13 @@
import s from './Logo.module.scss' import s from './Logo.module.scss'
interface Props { interface Props {
className?: string
children?: any
} }
const Logo = ({}: Props) => { const Logo = ({}: Props) => {
return( return(
<div className={s.logo}> <div className={s.logo}>
<div className={s.eclipse}> <div className={s.eclipse}>
</div> </div>
<div className={s.conTent}> <div className={s.conTent}>
ONLINE GROCERY ONLINE GROCERY

View File

@ -1,24 +1,30 @@
.productCardWarpper{ .productCardWarpper{
max-width: 20.8rem; width: 20.8rem;
max-height: 31.8rem; height: 31.8rem;
padding: 1.2rem 1.2rem 0 1.2rem; padding: 1.2rem 1.2rem 0 1.2rem;
@apply border border-solid border-black; margin-bottom: 1px;
@apply inline-flex flex-col justify-between;
.cardTop{ .cardTop{
@apply border border-solid border-yellow-300 relative; @apply relative;
max-height: 13.8rem; height: 13.8rem;
width: 100%;
.productImage{ .productImage{
height: 100%;
width: 100%;
@apply flex justify-center items-center; @apply flex justify-center items-center;
img{ img{
@apply inline; @apply inline;
} }
.productLabel{ }
@apply absolute left-0 bottom-0; .productLabel{
} @apply absolute left-0 bottom-0;
} }
} }
.cardMid{ .cardMid{
padding: 1.6rem 0; // padding: 1.6rem 0;
.cardMid{ min-height: 10.4rem;
@apply flex flex-col justify-between;
.cardMidTop{
.productname{ .productname{
font-weight: bold; font-weight: bold;
line-height: 2.4rem; line-height: 2.4rem;
@ -33,7 +39,6 @@
} }
} }
.cardMidBot{ .cardMidBot{
margin-top: 2.8rem;
@apply flex justify-between items-center border-t border-solid border-line; @apply flex justify-between items-center border-t border-solid border-line;
.productPrice{ .productPrice{
@apply font-bold; @apply font-bold;
@ -44,6 +49,7 @@
} }
} }
.cardBot{ .cardBot{
max-height: 4rem;
@apply flex justify-between items-center; @apply flex justify-between items-center;
.cardButton{ .cardButton{
width: 13.6rem; width: 13.6rem;

View File

@ -1,17 +1,13 @@
import React from 'react' import React from 'react'
import { ProductProps } from 'src/utils/types.utils'
import ButtonCommon from '../ButtonCommon/ButtonCommon' import ButtonCommon from '../ButtonCommon/ButtonCommon'
import ButtonIconBuy from '../ButtonIconBuy/ButtonIconBuy' import ButtonIconBuy from '../ButtonIconBuy/ButtonIconBuy'
import ItemWishList from '../ItemWishList/ItemWishList' import ItemWishList from '../ItemWishList/ItemWishList'
import LabelCommon from '../LabelCommon/LabelCommon' import LabelCommon from '../LabelCommon/LabelCommon'
import s from './ProductCard.module.scss' import s from './ProductCard.module.scss'
interface ProductCardProps { export interface ProductCardProps extends ProductProps {
category: string
name: string
weight: string
price: string
buttonText?: string buttonText?: string
imageSrc: string
} }
const ProductCard = ({ const ProductCard = ({
@ -23,16 +19,16 @@ const ProductCard = ({
imageSrc, imageSrc,
}: ProductCardProps) => { }: ProductCardProps) => {
return ( return (
<section className={s.productCardWarpper}> <div className={s.productCardWarpper}>
<section className={s.cardTop}> <div className={s.cardTop}>
<div className={s.productImage}> <div className={s.productImage}>
<img src={imageSrc} alt="image" /> <img src={imageSrc} alt="image" />
</div>
<div className={s.productLabel}> <div className={s.productLabel}>
<LabelCommon shape="half">{category}</LabelCommon> <LabelCommon shape="half">{category}</LabelCommon>
</div> </div>
</div> </div>
</section> <div className={s.cardMid}>
<section className={s.cardMid}>
<div className={s.cardMidTop}> <div className={s.cardMidTop}>
<div className={s.productname}>{name} </div> <div className={s.productname}>{name} </div>
<div className={s.productWeight}>{weight}</div> <div className={s.productWeight}>{weight}</div>
@ -43,16 +39,16 @@ const ProductCard = ({
<ItemWishList /> <ItemWishList />
</div> </div>
</div> </div>
</section> </div>
<section className={s.cardBot}> <div className={s.cardBot}>
<div className={s.cardIcon}> <div className={s.cardIcon}>
<ButtonIconBuy/> <ButtonIconBuy/>
</div> </div>
<div className={s.cardButton}> <div className={s.cardButton}>
<ButtonCommon type="ghost">{buttonText}</ButtonCommon> <ButtonCommon type="ghost">{buttonText}</ButtonCommon>
</div> </div>
</section> </div>
</section> </div>
) )
} }

View File

@ -0,0 +1,12 @@
@import "../../../styles/utilities";
.productCardWarpper{
@apply spacing-horizontal;
:global(.customArrow) {
&:global(.leftArrow){
left: calc(-6.4rem - 2rem);
}
&:global(.rightArrow){
right: calc(-6.4rem - 2rem);
}
}
}

View File

@ -0,0 +1,39 @@
import { TOptionsEvents } from 'keen-slider'
import React from 'react'
import CarouselCommon, {
CarouselCommonProps,
} from '../CarouselCommon/CarouselCommon'
import ProductCard, { ProductCardProps } from '../ProductCard/ProductCard'
import s from "./ProductCaroucel.module.scss"
interface ProductCaroucelProps
extends Omit<CarouselCommonProps<ProductCardProps>, 'Component'|"option"> {
option?:TOptionsEvents
}
const OPTION_DEFAULT: TOptionsEvents = {
slidesPerView: 2,
mode: 'free',
breakpoints: {
'(min-width: 768px)': {
slidesPerView: 3,
},
'(min-width: 1024px)': {
slidesPerView: 5.5,
},
},
}
const ProductCaroucel = ({ option, data, ...props }: ProductCaroucelProps) => {
return (
<div className={s.productCardWarpper}>
<CarouselCommon<ProductCardProps>
data={data}
Component={ProductCard}
{...props}
option={{ ...OPTION_DEFAULT, ...option }}
/>
</div>
)
}
export default ProductCaroucel

View File

@ -1,16 +1,18 @@
@import '../../../styles/utilities'; @import '../../../styles/utilities';
@import url('https://fonts.googleapis.com/css2?family=Nunito&display=swap');
.viewAll{ .viewAll{
display: flex; display: flex;
color: theme("colors.primary"); color: theme("colors.primary");
.conTent{ .conTent{
margin: 0.8rem 0.8rem 0.8rem 1.6rem; margin: 0.8rem 0.8rem 0.8rem 1.6rem;
font-family: 'Nunito', sans-serif; font-family: var(--font-sans);
font-weight: bold; font-weight: bold;
} }
.vecTor{ .vecTor{
margin: 0.8rem 0rem 0.8rem 0rem; margin: 0.8rem 0rem 0.8rem 0rem;
svg path{
fill: theme("colors.primary");
}
} }
} }

View File

@ -1,10 +1,8 @@
import Vector from 'src/components/icons/Vector' import IconVector from 'src/components/icons/IconVector'
import s from './ViewAllItem.module.scss' import s from './ViewAllItem.module.scss'
import Link from 'next/link' import Link from 'next/link'
interface Props { interface Props {
className?: string
children?: any
link?: string link?: string
} }
@ -17,7 +15,7 @@ const ViewAllItem = ({ link }: Props) => {
</a> </a>
</Link> </Link>
<div className={s.vecTor}> <div className={s.vecTor}>
<Vector /> <IconVector />
</div> </div>
</div> </div>
) )

View File

@ -1,20 +0,0 @@
const Vector = ({ ...props }) => {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M20.16 4.99992C19.1 3.93713 17.6948 3.28846 16.1984 3.17109C14.7019 3.05372 13.2128 3.47539 12 4.35992C10.7277 3.41356 9.14402 2.98443 7.56795 3.15896C5.99188 3.33348 4.54047 4.0987 3.506 5.30051C2.47154 6.50231 1.93085 8.05144 1.99283 9.63594C2.05481 11.2204 2.71485 12.7226 3.84003 13.8399L10.05 20.0599C10.57 20.5717 11.2704 20.8585 12 20.8585C12.7296 20.8585 13.43 20.5717 13.95 20.0599L20.16 13.8399C21.3276 12.6652 21.983 11.0762 21.983 9.41992C21.983 7.76365 21.3276 6.17465 20.16 4.99992ZM18.75 12.4599L12.54 18.6699C12.4694 18.7413 12.3853 18.7979 12.2926 18.8366C12.1999 18.8752 12.1005 18.8951 12 18.8951C11.8996 18.8951 11.8002 18.8752 11.7075 18.8366C11.6148 18.7979 11.5307 18.7413 11.46 18.6699L5.25003 12.4299C4.46579 11.6283 4.02664 10.5514 4.02664 9.42992C4.02664 8.30846 4.46579 7.23158 5.25003 6.42992C6.04919 5.64091 7.127 5.19849 8.25003 5.19849C9.37306 5.19849 10.4509 5.64091 11.25 6.42992C11.343 6.52365 11.4536 6.59804 11.5755 6.64881C11.6973 6.69958 11.828 6.72572 11.96 6.72572C12.092 6.72572 12.2227 6.69958 12.3446 6.64881C12.4665 6.59804 12.5771 6.52365 12.67 6.42992C13.4692 5.64091 14.547 5.19849 15.67 5.19849C16.7931 5.19849 17.8709 5.64091 18.67 6.42992C19.4651 7.22107 19.9186 8.29211 19.9336 9.41361C19.9485 10.5351 19.5237 11.6179 18.75 12.4299V12.4599Z"
fill={props.color}
/>
</svg>
)
}
export default Vector

View File

@ -0,0 +1,23 @@
const IconHeart = ({ ...props }) => {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M20.84 2.61C20.3292 2.099 19.7228 1.69365 19.0554 1.41708C18.3879 1.14052 17.6725 0.998175 16.95 0.998175C16.2275 0.998175 15.5121 1.14052 14.8446 1.41708C14.1772 1.69365 13.5708 2.099 13.06 2.61L12 3.67L10.94 2.61C9.9083 1.57831 8.50903 0.998709 7.05 0.998709C5.59096 0.998709 4.19169 1.57831 3.16 2.61C2.1283 3.64169 1.54871 5.04097 1.54871 6.5C1.54871 7.95903 2.1283 9.35831 3.16 10.39L4.22 11.45L12 19.23L19.78 11.45L20.84 10.39C21.351 9.87924 21.7563 9.27281 22.0329 8.60536C22.3095 7.9379 22.4518 7.22249 22.4518 6.5C22.4518 5.77751 22.3095 5.0621 22.0329 4.39464C21.7563 3.72719 21.351 3.12076 20.84 2.61V2.61Z"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
}
export default IconHeart

View File

@ -1,5 +1,5 @@
const Vector = ({ ...props }) => { const IconVector = ({ ...props }) => {
return ( return (
<svg <svg
width="24" width="24"
@ -11,10 +11,9 @@ const Vector = ({ ...props }) => {
> >
<path <path
d="M14.8299 11.2899L10.5899 7.04995C10.497 6.95622 10.3864 6.88183 10.2645 6.83106C10.1427 6.78029 10.012 6.75415 9.87994 6.75415C9.74793 6.75415 9.61723 6.78029 9.49537 6.83106C9.37351 6.88183 9.26291 6.95622 9.16994 7.04995C8.98369 7.23731 8.87915 7.49076 8.87915 7.75495C8.87915 8.01913 8.98369 8.27259 9.16994 8.45995L12.7099 11.9999L9.16994 15.5399C8.98369 15.7273 8.87915 15.9808 8.87915 16.2449C8.87915 16.5091 8.98369 16.7626 9.16994 16.9499C9.26338 17.0426 9.3742 17.116 9.49604 17.1657C9.61787 17.2155 9.74834 17.2407 9.87994 17.2399C10.0115 17.2407 10.142 17.2155 10.2638 17.1657C10.3857 17.116 10.4965 17.0426 10.5899 16.9499L14.8299 12.7099C14.9237 12.617 14.9981 12.5064 15.0488 12.3845C15.0996 12.2627 15.1257 12.132 15.1257 11.9999C15.1257 11.8679 15.0996 11.7372 15.0488 11.6154C14.9981 11.4935 14.9237 11.3829 14.8299 11.2899Z" d="M14.8299 11.2899L10.5899 7.04995C10.497 6.95622 10.3864 6.88183 10.2645 6.83106C10.1427 6.78029 10.012 6.75415 9.87994 6.75415C9.74793 6.75415 9.61723 6.78029 9.49537 6.83106C9.37351 6.88183 9.26291 6.95622 9.16994 7.04995C8.98369 7.23731 8.87915 7.49076 8.87915 7.75495C8.87915 8.01913 8.98369 8.27259 9.16994 8.45995L12.7099 11.9999L9.16994 15.5399C8.98369 15.7273 8.87915 15.9808 8.87915 16.2449C8.87915 16.5091 8.98369 16.7626 9.16994 16.9499C9.26338 17.0426 9.3742 17.116 9.49604 17.1657C9.61787 17.2155 9.74834 17.2407 9.87994 17.2399C10.0115 17.2407 10.142 17.2155 10.2638 17.1657C10.3857 17.116 10.4965 17.0426 10.5899 16.9499L14.8299 12.7099C14.9237 12.617 14.9981 12.5064 15.0488 12.3845C15.0996 12.2627 15.1257 12.132 15.1257 11.9999C15.1257 11.8679 15.0996 11.7372 15.0488 11.6154C14.9981 11.4935 14.9237 11.3829 14.8299 11.2899Z"
fill="#5B9A74"
/> />
</svg> </svg>
) )
} }
export default Vector export default IconVector

7
src/utils/types.utils.ts Normal file
View File

@ -0,0 +1,7 @@
export interface ProductProps {
category: string
name: string
weight: string
price: string
imageSrc: string
}