mirror of
https://github.com/vercel/commerce.git
synced 2025-07-22 12:24:18 +00:00
pull m4-datnguyen
This commit is contained in:
343
pages/test.tsx
343
pages/test.tsx
@@ -3,14 +3,150 @@ import {
|
|||||||
ButtonCommon,
|
ButtonCommon,
|
||||||
Layout,
|
Layout,
|
||||||
ModalCommon,
|
ModalCommon,
|
||||||
|
ModalConfirm,
|
||||||
|
ModalInfo,
|
||||||
ProductCarousel,
|
ProductCarousel,
|
||||||
|
ProductList,
|
||||||
} from 'src/components/common'
|
} from 'src/components/common'
|
||||||
import { CollectionCarcousel } from 'src/components/modules/home'
|
import PaginationCommon from 'src/components/common/PaginationCommon/PaginationCommon'
|
||||||
import image5 from '../public/assets/images/image5.png'
|
import image5 from '../public/assets/images/image5.png'
|
||||||
import image6 from '../public/assets/images/image6.png'
|
import image6 from '../public/assets/images/image6.png'
|
||||||
import image7 from '../public/assets/images/image7.png'
|
import image7 from '../public/assets/images/image7.png'
|
||||||
import image8 from '../public/assets/images/image8.png'
|
import image8 from '../public/assets/images/image8.png'
|
||||||
const dataTest = [
|
const dataTest = [
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tomato',
|
||||||
|
weight: '250g',
|
||||||
|
category: 'VEGGIE',
|
||||||
|
price: 'Rp 27.500',
|
||||||
|
imageSrc: image5.src,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Tomato',
|
name: 'Tomato',
|
||||||
weight: '250g',
|
weight: '250g',
|
||||||
@@ -46,6 +182,132 @@ const dataTest = [
|
|||||||
price: 'Rp 27.500',
|
price: 'Rp 27.500',
|
||||||
imageSrc: image5.src,
|
imageSrc: image5.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: '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: '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: '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: '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: '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',
|
name: 'Cucumber',
|
||||||
weight: '250g',
|
weight: '250g',
|
||||||
@@ -81,6 +343,48 @@ const dataTest = [
|
|||||||
price: 'Rp 27.500',
|
price: 'Rp 27.500',
|
||||||
imageSrc: image8.src,
|
imageSrc: image8.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: '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: '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',
|
name: 'Tomato',
|
||||||
weight: '250g',
|
weight: '250g',
|
||||||
@@ -107,38 +411,11 @@ export default function Test() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ButtonCommon onClick={onOpen}>open</ButtonCommon>
|
<ButtonCommon onClick={onOpen}>open</ButtonCommon>
|
||||||
<ModalCommon visible={visible} onClose={onClose}>
|
<ModalInfo visible={visible} onClose={onClose}>
|
||||||
<div className="">
|
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Nisi qui, esse eos nobis soluta suscipit aliquid nostrum corporis. Nihil eligendi similique recusandae minus mollitia aliquam, molestias fugit tenetur voluptatibus maiores et. Quaerat labore corporis inventore nostrum, amet autem exercitationem eligendi?
|
||||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consectetur
|
</ModalInfo>
|
||||||
officiis dolorum ea incidunt. Sint, cum ullam. Labore vero quod
|
<PaginationCommon total={40} pageSize={10}/>
|
||||||
itaque, officia magni molestias! Architecto deserunt soluta laborum
|
<ProductList data={dataTest}/>
|
||||||
commodi nesciunt delectus similique temporibus distinctio? Facere
|
|
||||||
eaque minima enim modi magni, laudantium, animi mollitia beatae
|
|
||||||
repudiandae maxime labore error nesciunt, nisi est?
|
|
||||||
</div>
|
|
||||||
</ModalCommon>
|
|
||||||
<ProductCarousel
|
|
||||||
data={dataTest}
|
|
||||||
itemKey="product-2"
|
|
||||||
isDot
|
|
||||||
option={{
|
|
||||||
slidesPerView: 1,
|
|
||||||
breakpoints: {
|
|
||||||
'(min-width: 640px)': {
|
|
||||||
slidesPerView: 3,
|
|
||||||
},
|
|
||||||
'(min-width: 768px)': {
|
|
||||||
slidesPerView: 4,
|
|
||||||
},
|
|
||||||
'(min-width: 1024px)': {
|
|
||||||
slidesPerView: 4.5,
|
|
||||||
},
|
|
||||||
'(min-width: 1280px)': {
|
|
||||||
slidesPerView: 5.5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -13,10 +13,16 @@
|
|||||||
}
|
}
|
||||||
@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 left-0;
|
@apply hidden left-0;
|
||||||
|
@screen md {
|
||||||
|
@apply flex
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&:global(.rightArrow) {
|
&:global(.rightArrow) {
|
||||||
@apply right-0;
|
@apply hidden right-0;
|
||||||
|
@screen md {
|
||||||
|
@apply flex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&:global(.isDisabledArrow) {
|
&:global(.isDisabledArrow) {
|
||||||
@apply hidden;
|
@apply hidden;
|
||||||
|
@@ -1,20 +1,2 @@
|
|||||||
.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 ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@ import React, { useRef } from 'react'
|
|||||||
import { Close } from 'src/components/icons'
|
import { Close } from 'src/components/icons'
|
||||||
import { useOnClickOutside } from 'src/utils/useClickOutSide'
|
import { useOnClickOutside } from 'src/utils/useClickOutSide'
|
||||||
import s from './ModalCommon.module.scss'
|
import s from './ModalCommon.module.scss'
|
||||||
interface Props {
|
export interface ModalCommonProps {
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
visible: boolean
|
visible: boolean
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
@@ -10,7 +10,7 @@ interface Props {
|
|||||||
maxWidth?:string
|
maxWidth?:string
|
||||||
}
|
}
|
||||||
|
|
||||||
const ModalCommon = ({ onClose, visible, children, title="Modal",maxWidth }: Props) => {
|
const ModalCommon = ({ onClose, visible, children, title="Modal",maxWidth }: ModalCommonProps) => {
|
||||||
const modalRef = useRef<HTMLDivElement>(null)
|
const modalRef = useRef<HTMLDivElement>(null)
|
||||||
const clickOutSide = () => {
|
const clickOutSide = () => {
|
||||||
onClose && onClose()
|
onClose && onClose()
|
||||||
|
@@ -0,0 +1,4 @@
|
|||||||
|
.footer{
|
||||||
|
margin-top: 4rem;
|
||||||
|
@apply flex justify-end items-center;
|
||||||
|
}
|
34
src/components/common/ModalConfirm/ModalConfirm.tsx
Normal file
34
src/components/common/ModalConfirm/ModalConfirm.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import ButtonCommon from '../ButtonCommon/ButtonCommon'
|
||||||
|
import ModalCommon, { ModalCommonProps } from '../ModalCommon/ModalCommon'
|
||||||
|
import s from './ModalConfirm.module.scss'
|
||||||
|
interface ModalConfirmProps extends ModalCommonProps {
|
||||||
|
okText?: String
|
||||||
|
cancelText?: String
|
||||||
|
onOk?: () => void
|
||||||
|
onCancel?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const ModalConfirm = ({
|
||||||
|
okText = 'Ok',
|
||||||
|
cancelText = 'cancel',
|
||||||
|
onOk,
|
||||||
|
onCancel,
|
||||||
|
children,
|
||||||
|
title = 'Confirm',
|
||||||
|
...props
|
||||||
|
}: ModalConfirmProps) => {
|
||||||
|
return (
|
||||||
|
<ModalCommon {...props} title={title}>
|
||||||
|
{children}
|
||||||
|
<div className={s.footer}>
|
||||||
|
<div className="mr-4">
|
||||||
|
<ButtonCommon onClick={onCancel} type="light"> {cancelText}</ButtonCommon>
|
||||||
|
</div>
|
||||||
|
<ButtonCommon onClick={onOk}>{okText}</ButtonCommon>
|
||||||
|
</div>
|
||||||
|
</ModalCommon>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ModalConfirm
|
4
src/components/common/ModalInfo/ModalInfo.module.scss
Normal file
4
src/components/common/ModalInfo/ModalInfo.module.scss
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.footer{
|
||||||
|
margin-top: 4rem;
|
||||||
|
@apply flex justify-end items-center;
|
||||||
|
}
|
27
src/components/common/ModalInfo/ModalInfo.tsx
Normal file
27
src/components/common/ModalInfo/ModalInfo.tsx
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import ButtonCommon from '../ButtonCommon/ButtonCommon'
|
||||||
|
import ModalCommon, { ModalCommonProps } from '../ModalCommon/ModalCommon'
|
||||||
|
import s from './ModalInfo.module.scss'
|
||||||
|
interface ModalInfoProps extends ModalCommonProps {
|
||||||
|
okText?: String
|
||||||
|
onOk?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const ModalInfo = ({
|
||||||
|
okText = 'Ok',
|
||||||
|
onOk,
|
||||||
|
children,
|
||||||
|
title = 'Confirm',
|
||||||
|
...props
|
||||||
|
}: ModalInfoProps) => {
|
||||||
|
return (
|
||||||
|
<ModalCommon {...props} title={title}>
|
||||||
|
{children}
|
||||||
|
<div className={s.footer}>
|
||||||
|
<ButtonCommon onClick={onOk}>{okText}</ButtonCommon>
|
||||||
|
</div>
|
||||||
|
</ModalCommon>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ModalInfo
|
@@ -0,0 +1,22 @@
|
|||||||
|
.warpper{
|
||||||
|
.item{
|
||||||
|
@apply inline-flex items-center justify-center cursor-pointer;
|
||||||
|
background-color: var(--gray);
|
||||||
|
margin: 0 0.4rem;
|
||||||
|
width: 3.2rem;
|
||||||
|
height: 3.2rem;
|
||||||
|
&.active{
|
||||||
|
@apply border border-solid;
|
||||||
|
border-color: var(--text-active);
|
||||||
|
background-color: var(--white);
|
||||||
|
}
|
||||||
|
&.disable{
|
||||||
|
svg{
|
||||||
|
path{
|
||||||
|
fill: var(--disabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@apply text-disabled cursor-not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
74
src/components/common/PaginationCommon/PaginationCommon.tsx
Normal file
74
src/components/common/PaginationCommon/PaginationCommon.tsx
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import classNames from 'classnames'
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { ArrowLeftSmall, ArrowRightSmall } from 'src/components/icons'
|
||||||
|
import PaginationItem from './components/PaginationItem'
|
||||||
|
import s from './PaginationCommon.module.scss'
|
||||||
|
interface PaginationCommonProps {
|
||||||
|
defaultCurrent?: number
|
||||||
|
pageSize: number
|
||||||
|
total: number
|
||||||
|
onChange?: (page: number, pageSize: number) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const PaginationCommon = ({
|
||||||
|
total,
|
||||||
|
pageSize,
|
||||||
|
defaultCurrent,
|
||||||
|
onChange,
|
||||||
|
}: PaginationCommonProps) => {
|
||||||
|
const [pageNum, setPageNum] = useState<number>(0)
|
||||||
|
const [currentPage, setCurrentPage] = useState<number>(0)
|
||||||
|
useEffect(() => {
|
||||||
|
setPageNum(Math.ceil(total / pageSize))
|
||||||
|
}, [total, pageSize])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (defaultCurrent) {
|
||||||
|
setCurrentPage(defaultCurrent)
|
||||||
|
}
|
||||||
|
}, [defaultCurrent])
|
||||||
|
|
||||||
|
const onPageClick = (page: number) => {
|
||||||
|
setCurrentPage(page)
|
||||||
|
onChange && onChange(page, pageSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onPrevClick = () => {
|
||||||
|
setCurrentPage(currentPage - 1 < 0 ? 0 : currentPage - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onNextClick = () => {
|
||||||
|
setCurrentPage((currentPage + 1) > (pageNum - 1) ? (pageNum - 1) : currentPage + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={s.warpper}>
|
||||||
|
<div
|
||||||
|
className={classNames(s.item, { [`${s.disable}`]: currentPage <= 0 })}
|
||||||
|
onClick={onPrevClick}
|
||||||
|
>
|
||||||
|
<ArrowLeftSmall disable={currentPage <= 0} />
|
||||||
|
</div>
|
||||||
|
{[...Array(pageNum).keys()].map((index) => {
|
||||||
|
return (
|
||||||
|
<PaginationItem
|
||||||
|
page={index}
|
||||||
|
onClick={onPageClick}
|
||||||
|
key={`${index}-item`}
|
||||||
|
active={index === currentPage}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
<div
|
||||||
|
className={classNames(s.item, {
|
||||||
|
[`${s.disable}`]: currentPage >= pageNum - 1,
|
||||||
|
})}
|
||||||
|
onClick={onNextClick}
|
||||||
|
>
|
||||||
|
<ArrowRightSmall disable={currentPage >= pageNum} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PaginationCommon
|
@@ -0,0 +1,21 @@
|
|||||||
|
import classNames from 'classnames'
|
||||||
|
import React from 'react'
|
||||||
|
import s from "../PaginationCommon.module.scss"
|
||||||
|
interface PaginationItemProps {
|
||||||
|
onClick:(page:number)=>void
|
||||||
|
page:number
|
||||||
|
active:boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const PaginationItem = ({onClick, page, active}: PaginationItemProps) => {
|
||||||
|
const onPageClick = () => {
|
||||||
|
onClick && onClick(page)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div onClick={onPageClick} className={classNames(s.item,{[`${s.active}`]:active})}>
|
||||||
|
{page+1}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PaginationItem
|
@@ -57,7 +57,8 @@
|
|||||||
.cardBot{
|
.cardBot{
|
||||||
min-height: 4rem;
|
min-height: 4rem;
|
||||||
@apply flex justify-between items-center;
|
@apply flex justify-between items-center;
|
||||||
.cardButton{
|
.cardIcon{
|
||||||
|
margin-right: 0.8rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
11
src/components/common/ProductList/ProductList.module.scss
Normal file
11
src/components/common/ProductList/ProductList.module.scss
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
.wrapper{
|
||||||
|
.list{
|
||||||
|
// max-width: 109.4rem;
|
||||||
|
@apply flex flex-wrap justify-around;
|
||||||
|
}
|
||||||
|
.pagination{
|
||||||
|
padding-top: 4.8rem;
|
||||||
|
// max-width: 109.4rem;
|
||||||
|
@apply flex justify-center items-center ;
|
||||||
|
}
|
||||||
|
}
|
30
src/components/common/ProductList/ProductList.tsx
Normal file
30
src/components/common/ProductList/ProductList.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import React, { useState } from 'react'
|
||||||
|
import PaginationCommon from '../PaginationCommon/PaginationCommon'
|
||||||
|
import ProductCard, { ProductCardProps } from '../ProductCard/ProductCard'
|
||||||
|
import s from "./ProductList.module.scss"
|
||||||
|
interface ProductListProps {
|
||||||
|
data: ProductCardProps[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProductList = ({data}: ProductListProps) => {
|
||||||
|
const [currentPage, setCurrentPage] = useState(0)
|
||||||
|
const onPageChange = (page:number) => {
|
||||||
|
setCurrentPage(page)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className={s.wrapper}>
|
||||||
|
<div className={s.list}>
|
||||||
|
{
|
||||||
|
data.slice(currentPage*20,(currentPage+1)*20).map((product,index)=>{
|
||||||
|
return <ProductCard {...product} key={index}/>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div className={s.pagination}>
|
||||||
|
<PaginationCommon total={data.length} pageSize={20} onChange={onPageChange}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProductList
|
@@ -29,6 +29,9 @@ export { default as NotiMessage} from './NotiMessage/NotiMessage'
|
|||||||
export { default as VideoPlayer} from './VideoPlayer/VideoPlayer'
|
export { default as VideoPlayer} from './VideoPlayer/VideoPlayer'
|
||||||
export { default as SelectCommon} from './SelectCommon/SelectCommon'
|
export { default as SelectCommon} from './SelectCommon/SelectCommon'
|
||||||
export { default as ModalCommon} from './ModalCommon/ModalCommon'
|
export { default as ModalCommon} from './ModalCommon/ModalCommon'
|
||||||
|
export { default as ModalConfirm} from "./ModalConfirm/ModalConfirm"
|
||||||
|
export { default as ModalInfo} from "./ModalInfo/ModalInfo"
|
||||||
|
export { default as ProductList} from "./ProductList/ProductList"
|
||||||
export { default as ModalCreateUserInfo} from './ModalCreateUserInfo/ModalCreateUserInfo'
|
export { default as ModalCreateUserInfo} from './ModalCreateUserInfo/ModalCreateUserInfo'
|
||||||
export { default as CardBlog} from './CardBlog/CardBlog'
|
export { default as CardBlog} from './CardBlog/CardBlog'
|
||||||
export { default as RelevantBlogPosts} from './RelevantBlogPosts/RelevantBlogPosts'
|
export { default as RelevantBlogPosts} from './RelevantBlogPosts/RelevantBlogPosts'
|
||||||
|
18
src/components/icons/ArrowLeftSmall.tsx
Normal file
18
src/components/icons/ArrowLeftSmall.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
const ArrowLeft = ({ ...props }) => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="8"
|
||||||
|
height="12"
|
||||||
|
viewBox="0 0 8 12"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M3.28982 6.00019L6.82982 2.46019C7.01607 2.27283 7.12061 2.01938 7.12061 1.75519C7.12061 1.49101 7.01607 1.23756 6.82982 1.05019C6.73686 0.956464 6.62626 0.88207 6.5044 0.831301C6.38254 0.780533 6.25183 0.754395 6.11982 0.754395C5.98781 0.754395 5.8571 0.780533 5.73524 0.831301C5.61339 0.88207 5.50278 0.956464 5.40982 1.05019L1.16982 5.29019C1.07609 5.38316 1.0017 5.49376 0.950931 5.61562C0.900162 5.73747 0.874023 5.86818 0.874023 6.00019C0.874023 6.1322 0.900162 6.26291 0.950931 6.38477C1.0017 6.50663 1.07609 6.61723 1.16982 6.71019L5.40982 11.0002C5.50326 11.0929 5.61408 11.1662 5.73592 11.216C5.85775 11.2657 5.98821 11.291 6.11982 11.2902C6.25143 11.291 6.38189 11.2657 6.50373 11.216C6.62557 11.1662 6.73638 11.0929 6.82982 11.0002C7.01607 10.8128 7.12061 10.5594 7.12061 10.2952C7.12061 10.031 7.01607 9.77756 6.82982 9.59019L3.28982 6.00019Z"
|
||||||
|
fill="#141414"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ArrowLeft
|
18
src/components/icons/ArrowRightSmall.tsx
Normal file
18
src/components/icons/ArrowRightSmall.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
const ArrowRight = ({ ...props }) => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="8"
|
||||||
|
height="12"
|
||||||
|
viewBox="0 0 8 12"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M6.8297 5.29019L2.5897 1.05019C2.49674 0.956464 2.38613 0.88207 2.26428 0.831301C2.14242 0.780533 2.01171 0.754395 1.8797 0.754395C1.74769 0.754395 1.61698 0.780533 1.49512 0.831301C1.37326 0.88207 1.26266 0.956464 1.1697 1.05019C0.983448 1.23756 0.878906 1.49101 0.878906 1.75519C0.878906 2.01938 0.983448 2.27283 1.1697 2.46019L4.7097 6.00019L1.1697 9.54019C0.983448 9.72756 0.878906 9.98101 0.878906 10.2452C0.878906 10.5094 0.983448 10.7628 1.1697 10.9502C1.26314 11.0429 1.37395 11.1162 1.49579 11.166C1.61763 11.2157 1.74809 11.241 1.8797 11.2402C2.01131 11.241 2.14177 11.2157 2.26361 11.166C2.38544 11.1162 2.49626 11.0429 2.5897 10.9502L6.8297 6.71019C6.92343 6.61723 6.99782 6.50663 7.04859 6.38477C7.09936 6.26291 7.1255 6.1322 7.1255 6.00019C7.1255 5.86818 7.09936 5.73747 7.04859 5.61562C6.99782 5.49376 6.92343 5.38316 6.8297 5.29019Z"
|
||||||
|
fill="#141414"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ArrowRight
|
@@ -15,6 +15,8 @@ export { default as IconGoogleColor } from './IconGoogleColor'
|
|||||||
export { default as IconApple } from './IconApple'
|
export { default as IconApple } from './IconApple'
|
||||||
export { default as ArrowLeft } from './ArrowLeft'
|
export { default as ArrowLeft } from './ArrowLeft'
|
||||||
export { default as ArrowRight } from './ArrowRight'
|
export { default as ArrowRight } from './ArrowRight'
|
||||||
|
export { default as ArrowLeftSmall } from './ArrowLeftSmall'
|
||||||
|
export { default as ArrowRightSmall } from './ArrowRightSmall'
|
||||||
export { default as Close } from './Close'
|
export { default as Close } from './Close'
|
||||||
export { default as IconPassword } from './IconPassword'
|
export { default as IconPassword } from './IconPassword'
|
||||||
export { default as IconPasswordCross } from './IconPasswordCross'
|
export { default as IconPasswordCross } from './IconPasswordCross'
|
||||||
|
@@ -109,12 +109,13 @@ module.exports = {
|
|||||||
rounded: '.8rem',
|
rounded: '.8rem',
|
||||||
},
|
},
|
||||||
screens: {
|
screens: {
|
||||||
|
'sm-only': {'min': '0', 'max': '767px'},
|
||||||
'sm': '640px',
|
'sm': '640px',
|
||||||
// => @media (min-width: 640px) { ... }
|
// => @media (min-width: 640px) { ... }
|
||||||
|
'md-only': {'min': '768px', 'max': '1023px'},
|
||||||
'md': '768px',
|
'md': '768px',
|
||||||
// => @media (min-width: 768px) { ... }
|
// => @media (min-width: 768px) { ... }
|
||||||
|
'lg-only': {'min': '1024px', 'max': '1279px'},
|
||||||
'lg': '1024px',
|
'lg': '1024px',
|
||||||
// => @media (min-width: 1024px) { ... }
|
// => @media (min-width: 1024px) { ... }
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user