diff --git a/package.json b/package.json
index 91a529d52..57df2ec3b 100644
--- a/package.json
+++ b/package.json
@@ -27,6 +27,8 @@
"classnames": "^2.3.1",
"cookie": "^0.4.1",
"email-validator": "^2.0.4",
+ "eslint": "^7.32.0",
+ "eslint-config-next": "^11.1.2",
"immutability-helper": "^3.1.1",
"js-cookie": "^2.2.1",
"keen-slider": "^5.5.1",
@@ -66,6 +68,7 @@
"@types/node": "^15.12.4",
"@types/react": "^17.0.8",
"deepmerge": "^4.2.2",
+ "eslint-config-prettier": "^8.3.0",
"graphql": "^15.5.1",
"husky": "^6.0.0",
"lint-staged": "^11.0.0",
diff --git a/pages/index.tsx b/pages/index.tsx
index a71748373..7d23ebadd 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -4,7 +4,7 @@ import { HomeBanner, HomeCategories, HomeCollection, HomeCTA, HomeFeature, HomeR
export default function Home() {
return (
<>
-
+
@@ -12,6 +12,9 @@ export default function Home() {
+
+ {/* // todo: uncomment */}
+ {/* */}
>
)
}
diff --git a/pages/test.tsx b/pages/test.tsx
index c21f4cd6c..42dced539 100644
--- a/pages/test.tsx
+++ b/pages/test.tsx
@@ -1,14 +1,44 @@
-import { useState } from 'react'
import {
- Layout
+ CollapseCommon, Layout, RelevantBlogPosts
} from 'src/components/common'
-import { DeliveryAndPolicyPage } from 'src/components/modules/delivery-policy'
-
+const COLLAPSE_DATA = [
+ {
+ title: "This is a subtitle",
+ content: [
+ "When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces.",
+ "Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to.",
+ "This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.",
+ ],
+ },
+ {
+ title: "This is a subtitle",
+ content: [
+ "When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces.",
+ "Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to.",
+ "This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.",
+ ],
+ },
+ {
+ title: "This is a subtitle",
+ content: [
+ "When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces.",
+ "Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to.",
+ "This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.",
+ ],
+ },
+ {
+ title: "This is a subtitle",
+ content: [
+ "When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces.",
+ "Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to.",
+ "This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.",
+ ],
+ },
+]
export default function Test() {
return (
<>
-
>
)
}
diff --git a/public/assets/bannerrecipes.png b/public/assets/bannerrecipes.png
new file mode 100644
index 000000000..91271cbd2
Binary files /dev/null and b/public/assets/bannerrecipes.png differ
diff --git a/public/bg-products.svg b/public/bg-products.svg
index 2118c3277..1eaa1df8b 100644
--- a/public/bg-products.svg
+++ b/public/bg-products.svg
@@ -1,7 +1,7 @@
-
-
-
-
+
+
+
+
diff --git a/src/components/common/BreadcrumbCommon/BreadcrumbCommon.module.scss b/src/components/common/BreadcrumbCommon/BreadcrumbCommon.module.scss
index 8f6c05bf7..95c8526e1 100644
--- a/src/components/common/BreadcrumbCommon/BreadcrumbCommon.module.scss
+++ b/src/components/common/BreadcrumbCommon/BreadcrumbCommon.module.scss
@@ -2,7 +2,10 @@
.breadcrumbCommon {
color: var(--text-base);
+<<<<<<< HEAD
+=======
.currentItem {
cursor: default;
}
+>>>>>>> a9f9f06eb9dee2a1ddefe907ff804237a78c5210
}
diff --git a/src/components/common/CardBlog/CardBlog.tsx b/src/components/common/CardBlog/CardBlog.tsx
index 17a796bc4..314a6a1fd 100644
--- a/src/components/common/CardBlog/CardBlog.tsx
+++ b/src/components/common/CardBlog/CardBlog.tsx
@@ -1,21 +1,27 @@
import Link from 'next/link'
import React from 'react'
-import { RecipeProps } from 'src/utils/types.utils'
+import { ROUTE } from 'src/utils/constanst.utils'
+import { BlogProps } from 'src/utils/types.utils'
import s from './CardBlog.module.scss'
-export interface BlogCardProps extends RecipeProps {
- link: string,
+export interface BlogCardProps extends BlogProps {
+ // todo: edit when intergrate API
+
}
-const CardBlog = ({ imageSrc, title, description, link }: BlogCardProps) => {
+const CardBlog = ({ imageSrc, title, description, slug }: BlogCardProps) => {
return (
diff --git a/src/components/common/CollapseCommon/CollapseChild/CollapseChild.tsx b/src/components/common/CollapseCommon/CollapseChild/CollapseChild.tsx
index 397b0dcda..408b0c397 100644
--- a/src/components/common/CollapseCommon/CollapseChild/CollapseChild.tsx
+++ b/src/components/common/CollapseCommon/CollapseChild/CollapseChild.tsx
@@ -1,15 +1,13 @@
import s from './CollapseChild.module.scss'
import { useState } from 'react'
import classNames from 'classnames'
-import Link from 'next/link'
interface CollapseProps{
title?: string,
content: string,
isToggle?: boolean,
- link?: string,
}
-const CollapseChild = ({title, content, isToggle=false, link="/"}: CollapseProps) => {
+const CollapseChild = ({title, content, isToggle=false}: CollapseProps) => {
const [isActive, changeActive] = useState(isToggle)
const handleToggle = () => {
@@ -23,9 +21,7 @@ const CollapseChild = ({title, content, isToggle=false, link="/"}: CollapseProps
onClick = { handleToggle }
>
diff --git a/src/components/common/Header/components/HeaderMenu/HeaderMenu.module.scss b/src/components/common/Header/components/HeaderMenu/HeaderMenu.module.scss
index 2832211c1..eaaabca70 100644
--- a/src/components/common/Header/components/HeaderMenu/HeaderMenu.module.scss
+++ b/src/components/common/Header/components/HeaderMenu/HeaderMenu.module.scss
@@ -42,7 +42,7 @@
@apply hidden;
@screen md {
@apply flex items-center list-none;
- li {
+ > li {
@apply flex justify-center items-center w-full;
&:not(:last-child) {
margin-right: 4.8rem;
@@ -53,7 +53,7 @@
a {
@appy no-underline;
&:hover {
- opacity: .8;
+ opacity: 0.8;
}
&.iconFavourite {
svg path {
@@ -61,7 +61,14 @@
}
}
}
-
+ .btnCart {
+ &:hover {
+ svg path {
+ fill: var(--primary);
+ opacity: 0.8;
+ }
+ }
+ }
}
}
}
diff --git a/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx b/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx
index aa962605d..05e0b38fa 100644
--- a/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx
+++ b/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx
@@ -68,7 +68,7 @@ const HeaderMenu = memo(({ isFull, openModalAuthen, openModalInfo }: Props) => {
-
+
diff --git a/src/components/common/Layout/Layout.tsx b/src/components/common/Layout/Layout.tsx
index e52e70d3e..17f520185 100644
--- a/src/components/common/Layout/Layout.tsx
+++ b/src/components/common/Layout/Layout.tsx
@@ -29,6 +29,10 @@ const Layout: FC
= ({ children }) => {
{children}
+ toggle card: {visibleCartDrawer.toString()}
+
diff --git a/src/components/common/MenuDropdown/MenuDropdown.module.scss b/src/components/common/MenuDropdown/MenuDropdown.module.scss
index ae5b76c3d..5332794ff 100644
--- a/src/components/common/MenuDropdown/MenuDropdown.module.scss
+++ b/src/components/common/MenuDropdown/MenuDropdown.module.scss
@@ -3,9 +3,6 @@
.menuDropdown {
@apply relative cursor-pointer;
width: fit-content;
- .label {
- all: unset;
- }
&:hover {
.label {
color: var(--primary);
@@ -20,10 +17,21 @@
}
.label {
+ all: unset;
@apply flex justify-end items-center transition-all duration-200;
svg path {
width: fit-content;
}
+ &:focus,
+ &:active {
+ color: var(--primary);
+ svg path {
+ fill: currentColor;
+ }
+ }
+ &:focus-visible {
+ outline: 2px solid #000;
+ }
}
&.arrow {
@@ -66,18 +74,9 @@
@apply rounded list-none bg-white;
border: 1px solid var(--text-active);
margin-top: 0.4rem;
- li {
+ > li {
@apply block w-full transition-all duration-200 cursor-pointer text-active;
- word-wrap: break-word;
- -webkit-hyphens: auto;
- -ms-hyphens: auto;
- -moz-hyphens: auto;
- hyphens: auto;
- overflow-x: hidden;
- position: relative;
- max-width: 15rem;
white-space: nowrap;
- text-overflow: ellipsis;
button {
all: unset;
color: currentColor;
diff --git a/src/components/common/MenuFilter/MenuFilter.module.scss b/src/components/common/MenuFilter/MenuFilter.module.scss
new file mode 100644
index 000000000..ecea2e119
--- /dev/null
+++ b/src/components/common/MenuFilter/MenuFilter.module.scss
@@ -0,0 +1,40 @@
+@import "../../../styles/utilities";
+.menuFilterWrapper{
+
+ @screen md {
+ @apply hidden;
+ }
+ .menuFilterHeading{
+ @apply sub-headline font-bold ;
+ color: var(--text-active);
+ font-feature-settings: 'salt' on;
+ margin: 0.8rem 0;
+ }
+ .menuFilterList{
+ @apply flex flex-wrap justify-start relative;
+ margin-bottom: 3rem;
+ box-sizing: border-box;
+ &::after{
+ @apply absolute;
+ top: 110%;
+ content: "";
+ width: 100%;
+ border-bottom: 1px solid var(--border-line);
+ }
+
+ li{
+ margin: 1rem 0;
+ padding:0;
+ div{
+ padding: 0.8rem 1.6rem;
+ margin-right: 0.8rem;
+ background-color: var(--gray);
+ border-radius: 0.8rem;
+ &.active {
+ color:white;
+ background-color: var(--primary);
+ }
+ }
+ }
+ }
+}
diff --git a/src/components/common/MenuFilter/MenuFilter.tsx b/src/components/common/MenuFilter/MenuFilter.tsx
new file mode 100644
index 000000000..454942734
--- /dev/null
+++ b/src/components/common/MenuFilter/MenuFilter.tsx
@@ -0,0 +1,48 @@
+import classNames from 'classnames'
+import { useEffect, useState } from 'react';
+
+import s from './MenuFilter.module.scss'
+interface Props {
+ children?: any,
+ heading?:string,
+ categories:{name:string,link:string}[],
+ type:string,
+ onChangeValue?: (value: Object) => void
+}
+
+const MenuFilter = ({heading,categories,type,onChangeValue}:Props)=> {
+ const [active, setActive] = useState('');
+
+ function handleClick(link:string){
+ setActive(link);
+
+ if(active === link){
+ setActive('');
+ }
+ }
+
+ useEffect(()=>{
+
+ let href = active?.split("=");
+ const linkValue = href[1];
+
+ onChangeValue && onChangeValue({[type]:linkValue});
+ },[active])
+
+ return (
+
+ )
+}
+
+export default MenuFilter
diff --git a/src/components/common/MenuNavigation/MenuNavigation.module.scss b/src/components/common/MenuNavigation/MenuNavigation.module.scss
new file mode 100644
index 000000000..7535df707
--- /dev/null
+++ b/src/components/common/MenuNavigation/MenuNavigation.module.scss
@@ -0,0 +1,29 @@
+@import "../../../styles/utilities";
+.menuNavigationWrapper{
+ .menuNavigationHeading{
+ @screen md {
+ @apply sub-headline font-bold ;
+ color: var(--text-active);
+ font-feature-settings: 'salt' on;
+ margin: 1.6rem 0;
+ }
+ }
+ .menuNavigationList{
+ @screen md {
+ li{
+ margin: 0.8rem 0;
+ a{
+ display:block;
+ width:100%;
+ color:var(--text-base);
+ &:hover {
+ @apply text-primary;
+ }
+ &.active {
+ @apply text-primary;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/components/common/MenuNavigation/MenuNavigation.tsx b/src/components/common/MenuNavigation/MenuNavigation.tsx
new file mode 100644
index 000000000..4a8943051
--- /dev/null
+++ b/src/components/common/MenuNavigation/MenuNavigation.tsx
@@ -0,0 +1,34 @@
+import classNames from 'classnames'
+import Link from 'next/link'
+import { useRouter } from 'next/router'
+import s from './MenuNavigation.module.scss'
+
+interface Props {
+ children?: any,
+ heading:string,
+ categories:{name:string,link:string}[]
+}
+
+const MenuNavigation = ({heading,categories}:Props)=> {
+ const router = useRouter()
+
+ return (
+
+ {heading}({categories.length})
+
+
+ )
+}
+
+export default MenuNavigation
diff --git a/src/components/common/MenuNavigationProductList/MenuNavigationProductList.module.scss b/src/components/common/MenuNavigationProductList/MenuNavigationProductList.module.scss
new file mode 100644
index 000000000..aa3f5e6c3
--- /dev/null
+++ b/src/components/common/MenuNavigationProductList/MenuNavigationProductList.module.scss
@@ -0,0 +1,45 @@
+@import "../../../styles/utilities";
+.menuNavigationProductListDesktop{
+ @screen sm-only {
+ @apply hidden;
+ }
+}
+.menuNavigationProductListMobile{
+ @apply hidden;
+ &.isShow{
+ @apply block;
+ @screen md {
+ @apply hidden;
+ }
+ }
+ .menuNavigationProductModal{
+ background: rgba(0, 0, 0, 0.5);
+ position: fixed;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 10000;
+ .content{
+ @apply spacing-horizontal;
+ margin-top: 3rem;
+ padding-top: 2rem ;
+ padding-bottom: 5rem;
+ background-color: white;
+ overflow: auto;
+ height: 100%;
+ border-radius: 2.4rem 2.4rem 0 0;
+ .head{
+ @apply flex justify-between;
+ h3{
+ @apply heading-3 font-bold;
+ color:var(--text-base);
+ }
+ }
+ button{
+ margin-top: 2rem;
+ width: 100%;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/components/common/MenuNavigationProductList/MenuNavigationProductList.tsx b/src/components/common/MenuNavigationProductList/MenuNavigationProductList.tsx
new file mode 100644
index 000000000..d9ac2aa26
--- /dev/null
+++ b/src/components/common/MenuNavigationProductList/MenuNavigationProductList.tsx
@@ -0,0 +1,60 @@
+import React, { useState } from 'react';
+import {ButtonCommon} from 'src/components/common';
+import s from './MenuNavigationProductList.module.scss';
+import MenuSort from './MenuSort/MenuSort';
+import {LANGUAGE} from 'src/utils/language.utils';
+import classNames from 'classnames'
+import MenuFilter from '../MenuFilter/MenuFilter';
+import MenuNavigation from '../MenuNavigation/MenuNavigation';
+import IconHide from 'src/components/icons/IconHide';
+
+interface Props{
+ categories:{name:string,link:string}[],
+ brands:{name:string,link:string}[],
+ featured:{name:string,link:string}[],
+}
+
+const MenuNavigationProductList = ({categories,brands,featured}:Props)=>{
+
+ const [dataSort,setDataSort] = useState({});
+ const [isShow,setIsShow] = useState(true);
+
+ function handleValue(value:Object){
+ setDataSort({...dataSort,...value});
+ }
+ function filter(){
+ console.log(dataSort)
+ }
+
+ function hideMenu(){
+ if(isShow === true){
+ setIsShow(false);
+ }
+ }
+ return(
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {LANGUAGE.BUTTON_LABEL.CONFIRM}
+
+
+
+ >
+ )
+}
+
+export default MenuNavigationProductList
\ No newline at end of file
diff --git a/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.module.scss b/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.module.scss
new file mode 100644
index 000000000..a25752901
--- /dev/null
+++ b/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.module.scss
@@ -0,0 +1,46 @@
+@import "../../../../styles/utilities";
+.menuSortWrapper{
+
+ @screen md {
+ @apply hidden;
+ }
+ .menuSortHeading{
+ @apply sub-headline font-bold ;
+ color: var(--text-active);
+ font-feature-settings: 'salt' on;
+ margin: 0.8rem 0;
+ }
+ .menuSortList{
+ box-sizing: border-box;
+ &::after{
+ @apply absolute;
+ top: 110%;
+ content: "";
+ width: 100%;
+ border-bottom: 1px solid var(--border-line);
+ }
+ li{
+ div{
+ height: 4.8rem;
+ line-height: 4.8rem;
+ padding: 0 1.6rem;
+ margin-right: 0.8rem;
+ border-radius: 0.8rem;
+ &.active {
+ @apply font-bold relative;
+ color:var(--text-active);
+ background-color: var(--primary-lightest);
+ &::after{
+ @apply absolute;
+ content:"";
+ background-image: url('/assets/svg/check.svg');
+ right: 1.6rem;
+ top: calc(50% - 24px/2);
+ width: 2.4rem;
+ height: 2.4rem;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.tsx b/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.tsx
new file mode 100644
index 000000000..2e66dfc83
--- /dev/null
+++ b/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.tsx
@@ -0,0 +1,67 @@
+import classNames from 'classnames';
+import { useEffect, useState } from 'react';
+import { QUERY_KEY, ROUTE } from 'src/utils/constanst.utils';
+import s from './MenuSort.module.scss';
+
+interface Props {
+ children?: any,
+ heading:string,
+ type:string,
+ onChangeValue?: (value: Object) => void
+}
+const SORT = [
+ {
+ name: 'By Name',
+ link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.SORTBY}=by-name`,
+ },
+ {
+ name: 'Price(High to Low)',
+ link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.SORTBY}=high-to-low`,
+ },
+ {
+ name: 'Price (Low to High)',
+ link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.SORTBY}=low-to-high`,
+ },
+ {
+ name: 'On Sale',
+ link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.SORTBY}=on-sale`,
+ },
+ ];
+
+
+const MenuSort = ({heading,type,onChangeValue}:Props)=> {
+ const [active, setActive] = useState('');
+
+ function handleClick(link:string){
+ setActive(link);
+
+ if(active === link){
+ setActive('');
+ }
+ }
+
+ useEffect(()=>{
+
+ let href = active?.split("=");
+ const linkValue = href[1];
+
+ onChangeValue && onChangeValue({[type]:linkValue});
+ },[active])
+
+ return (
+
+ )
+}
+
+export default MenuSort
diff --git a/src/components/common/ModalAuthenticate/components/FormLogin/FormLogin.tsx b/src/components/common/ModalAuthenticate/components/FormLogin/FormLogin.tsx
index bedb993f4..b1059a441 100644
--- a/src/components/common/ModalAuthenticate/components/FormLogin/FormLogin.tsx
+++ b/src/components/common/ModalAuthenticate/components/FormLogin/FormLogin.tsx
@@ -1,7 +1,6 @@
import Link from 'next/link'
import React, { useEffect, useRef } from 'react'
-import { ButtonCommon, Inputcommon } from 'src/components/common'
-import InputPassword from 'src/components/common/InputPassword/InputPassword'
+import { ButtonCommon, Inputcommon, InputPassword } from 'src/components/common'
import { ROUTE } from 'src/utils/constanst.utils'
import { CustomInputCommon } from 'src/utils/type.utils'
import s from '../FormAuthen.module.scss'
diff --git a/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx b/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx
index d03dbc39e..66ec1f8a4 100644
--- a/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx
+++ b/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx
@@ -1,5 +1,5 @@
import React, { useEffect, useRef } from 'react'
-import { ButtonCommon, Inputcommon } from 'src/components/common'
+import { ButtonCommon, Inputcommon, InputPassword } from 'src/components/common'
import s from '../FormAuthen.module.scss'
import styles from './FormRegister.module.scss'
import SocialAuthen from '../SocialAuthen/SocialAuthen'
diff --git a/src/components/common/PaginationCommon/PaginationCommon.module.scss b/src/components/common/PaginationCommon/PaginationCommon.module.scss
index e69de29bb..6470cd72f 100644
--- a/src/components/common/PaginationCommon/PaginationCommon.module.scss
+++ b/src/components/common/PaginationCommon/PaginationCommon.module.scss
@@ -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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/components/common/PaginationCommon/PaginationCommon.tsx b/src/components/common/PaginationCommon/PaginationCommon.tsx
index 59bbd3baa..aed2473f3 100644
--- a/src/components/common/PaginationCommon/PaginationCommon.tsx
+++ b/src/components/common/PaginationCommon/PaginationCommon.tsx
@@ -1,15 +1,75 @@
-import React from 'react'
-
+import classNames from 'classnames'
+import React, { useEffect, useState } from 'react'
+import { ArrowLeftSmall, ArrowRightSmall } from 'src/components/icons'
+import { DEFAULT_PAGE_SIZE } from 'src/utils/constanst.utils'
+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 = (props: PaginationCommonProps) => {
- return (
-
-
-
- )
+const PaginationCommon = ({
+ total,
+ pageSize=DEFAULT_PAGE_SIZE,
+ defaultCurrent,
+ onChange,
+}: PaginationCommonProps) => {
+ const [pageNum, setPageNum] = useState(0)
+ const [currentPage, setCurrentPage] = useState(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 (
+
+
+ {[...Array(pageNum).keys()].map((index) => {
+ return (
+
+ )
+ })}
+
= pageNum - 1,
+ })}
+ onClick={onNextClick}
+ >
+
= pageNum} />
+
+
+ )
}
export default PaginationCommon
diff --git a/src/components/common/PaginationCommon/components/PaginationItem.tsx b/src/components/common/PaginationCommon/components/PaginationItem.tsx
new file mode 100644
index 000000000..e5f526bc4
--- /dev/null
+++ b/src/components/common/PaginationCommon/components/PaginationItem.tsx
@@ -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 (
+
+ {page+1}
+
+ )
+}
+
+export default PaginationItem
diff --git a/src/components/common/ProductCard/ProductCard.module.scss b/src/components/common/ProductCard/ProductCard.module.scss
index 73be21ab1..cffbe063b 100644
--- a/src/components/common/ProductCard/ProductCard.module.scss
+++ b/src/components/common/ProductCard/ProductCard.module.scss
@@ -59,7 +59,8 @@
.cardBot{
min-height: 4rem;
@apply flex justify-between items-center;
- .cardButton{
+ .cardIcon{
+ margin-right: 0.8rem;
}
}
}
\ No newline at end of file
diff --git a/src/components/common/ProductList/ProductList.module.scss b/src/components/common/ProductList/ProductList.module.scss
new file mode 100644
index 000000000..c49696ea5
--- /dev/null
+++ b/src/components/common/ProductList/ProductList.module.scss
@@ -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 ;
+ }
+}
\ No newline at end of file
diff --git a/src/components/common/ProductList/ProductList.tsx b/src/components/common/ProductList/ProductList.tsx
new file mode 100644
index 000000000..7428e3a63
--- /dev/null
+++ b/src/components/common/ProductList/ProductList.tsx
@@ -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 (
+
+
+ {
+ data.slice(currentPage*20,(currentPage+1)*20).map((product,index)=>{
+ return
+ })
+ }
+
+
+
+ )
+}
+
+export default ProductList
diff --git a/src/components/common/RelevantBlogPosts/RelevantBlogPosts.module.scss b/src/components/common/RelevantBlogPosts/RelevantBlogPosts.module.scss
index d5a13299d..ed232830f 100644
--- a/src/components/common/RelevantBlogPosts/RelevantBlogPosts.module.scss
+++ b/src/components/common/RelevantBlogPosts/RelevantBlogPosts.module.scss
@@ -1,6 +1,9 @@
@import '../../../styles/utilities';
.blogPostWarpper {
+ &.cream{
+ background-color: #F5F4F2;
+ }
padding-top: 5.6rem;
padding-bottom: 5.2rem;
@apply flex flex-col;
diff --git a/src/components/common/RelevantBlogPosts/RelevantBlogPosts.tsx b/src/components/common/RelevantBlogPosts/RelevantBlogPosts.tsx
index 01e19bb25..1d71a6ca1 100644
--- a/src/components/common/RelevantBlogPosts/RelevantBlogPosts.tsx
+++ b/src/components/common/RelevantBlogPosts/RelevantBlogPosts.tsx
@@ -1,6 +1,7 @@
import image15 from '../../../../public/assets/images/image15.png'
import image16 from '../../../../public/assets/images/image16.png'
import image17 from '../../../../public/assets/images/image17.png'
+import classNames from 'classnames'
import React from 'react'
import { HeadingCommon, ViewAllItem } from 'src/components/common'
import { BlogCardProps } from 'src/components/common/CardBlog/CardBlog'
@@ -9,54 +10,59 @@ import s from './RelevantBlogPosts.module.scss'
import { ROUTE } from 'src/utils/constanst.utils';
interface RelevantProps {
- data?: BlogCardProps[]
- itemKey?: string
- title?: string
- viewAllLink?: string
+ data?: BlogCardProps[],
+ itemKey?: string,
+ title?: string,
+ viewAllLink?: string,
+ bgcolor?: "default" | "cream"
}
const recipe:BlogCardProps[] = [
{
title: "Want to Lose Weight? Here are 10 DEBM Diet Guidelines for Beginners",
+ slug: 'have-a-nice-lunch',
description:"The DEBM diet stands for "+'"Delicious Happy Fun Diet"'+". This diet was popularized by Robert...",
imageSrc: image15.src,
- link: `${ROUTE.BLOG_DETAIL}`
},{
title: "9 Ways to Make an Aloe Vera Mask at Home",
+ slug: 'have-a-nice-lunch',
description:"Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...",
imageSrc: image16.src,
- link: `${ROUTE.BLOG_DETAIL}`
},{
title: "Don't Buy Wrong, Here Are 7 Ways to Choose a Ripe Dragon Fruit",
+ slug: 'have-a-nice-lunch',
description:"Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...",
imageSrc: image17.src,
- link: `${ROUTE.BLOG_DETAIL}`
},{
title: "Want to Lose Weight? Here are 10 DEBM Diet Guidelines for Beginners",
+ slug: 'have-a-nice-lunch',
description:"The DEBM diet stands for "+'"Delicious Happy Fun Diet"'+". This diet was popularized by Robert...",
imageSrc: image15.src,
- link: `${ROUTE.BLOG_DETAIL}`
},{
title: "9 Ways to Make an Aloe Vera Mask at Home",
+ slug: 'have-a-nice-lunch',
description:"Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...",
imageSrc: image16.src,
- link: `${ROUTE.BLOG_DETAIL}`
},{
title: "Don't Buy Wrong, Here Are 7 Ways to Choose a Ripe Dragon Fruit",
+ slug: 'have-a-nice-lunch',
description:"Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...",
imageSrc: image17.src,
- link: `${ROUTE.BLOG_DETAIL}`
}]
- const RelevantBlogPosts = ({ data = recipe, itemKey="detail-relevant", title="Relevant Blog Posts" }: RelevantProps) => {
+ const RelevantBlogPosts = ({ data = recipe, itemKey="detail-relevant", title="Relevant Blog Posts", bgcolor = "default" }: RelevantProps) => {
return (
-
+
diff --git a/src/components/common/SelectCommon/SelectCommon.module.scss b/src/components/common/SelectCommon/SelectCommon.module.scss
index d91b1831e..4809a46bb 100644
--- a/src/components/common/SelectCommon/SelectCommon.module.scss
+++ b/src/components/common/SelectCommon/SelectCommon.module.scss
@@ -1,69 +1,90 @@
@import "../../../styles/utilities";
-.select{
+.select {
background-color: var(--white);
- &.base{
+ .selectTrigger {
+ svg {
+ @apply transition-all duration-200;
+ }
+ }
+ &.base {
width: 20.6rem;
- .selectTrigger{
+ .selectTrigger {
width: 20.6rem;
padding: 1.2rem 1.6rem;
}
}
- &.large{
+ &.large {
width: 34.25rem;
- .selectTrigger{
+ .selectTrigger {
width: 34.25rem;
padding: 1.6rem 1.6rem;
}
}
- &.default{
- .selectTrigger{
+ &.default {
+ .selectTrigger {
@apply border-solid border border-current;
- }
+ }
}
- &.custom{
- .selectTrigger{
+ &.custom {
+ .selectTrigger {
@apply border-2;
border-color: var(--border-line);
color: var(--text-label);
}
}
- &.isActive{
- .selectOptionWrapper{
+ &:hover {
+ cursor: pointer;
+ .hoverWrapper {
@apply block;
+ animation: SelectAnimation 0.2s ease-out;
+ }
+ .selectTrigger {
+ svg {
+ transform: rotate(180deg);
+ }
}
}
}
-.selectTrigger{
+.selectTrigger {
@apply outline-none flex justify-between;
color: var(--text-active);
border-radius: 0.8rem;
-
}
-.selectOptionWrapper{
- @apply outline-none hidden z-10 absolute;
- border-radius: 0.8rem;
- background-color: var(--white);
- padding: 0.4rem 0rem 0.4rem 0rem;
- margin-top: 0.6rem;
- &.base{
- width: 20.6rem;
+.hoverWrapper {
+ @apply hidden outline-none absolute z-10;
+ padding-top: 0.6rem;
+ .selectOptionWrapper {
+ border-radius: 0.8rem;
+ background-color: var(--white);
+ padding: 0.4rem 0rem 0.4rem 0rem;
+ &.base {
+ width: 20.6rem;
+ }
+ &.large {
+ width: 34.25rem;
+ }
+ &.default {
+ @apply border-solid border border-current;
+ }
+ &.custom {
+ @apply border-2;
+ border-color: var(--border-line);
+ color: var(--text-label);
+ }
}
- &.large{
- width: 34.25rem;
- }
- &.default{
- @apply border-solid border border-current;
- }
- &.custom{
- @apply border-2;
- border-color: var(--border-line);
- color: var(--text-label);
- }
- &.active{
- @apply hidden;
+ &:hover {
+ @apply block;
}
}
-
-
+@keyframes SelectAnimation {
+ 0% {
+ opacity: 0;
+ transform: translateY(1.6rem);
+ }
+ 100% {
+ opacity: 1;
+ transform: none;
+ }
+}
diff --git a/src/components/common/SelectCommon/SelectCommon.tsx b/src/components/common/SelectCommon/SelectCommon.tsx
index 5bb3d15d6..9b8c88e24 100644
--- a/src/components/common/SelectCommon/SelectCommon.tsx
+++ b/src/components/common/SelectCommon/SelectCommon.tsx
@@ -1,43 +1,25 @@
import s from './SelectCommon.module.scss'
import classNames from 'classnames'
-import { useState, useRef, useEffect } from 'react'
+import { useState } from 'react'
import { IconVectorDown } from 'src/components/icons'
import SelectOption from './SelectOption/SelectOption'
interface Props {
- children? : React.ReactNode,
+ placeholder? : string,
size?: 'base' | 'large',
type?: 'default' | 'custom',
- option: {name: string}[],
+ option: {name: string, value: string}[],
+ onChange?: (value: string) => void,
}
-const SelectCommon = ({ type = 'default', size = 'base', option, children }: Props) => {
- const [isActive, setActive] = useState(false)
- const [selectedName, setSelectedName] = useState(children)
- const ref = useRef
(null)
-
- useEffect(() => {
- const handleClick = (event: MouseEvent) => {
- const { target } = event;
- if (!ref?.current || ref?.current.contains(target as Node)) {
- return
- }
- else{
- setActive(false)
- }
- }
- document.addEventListener('click', handleClick)
- return () => {
- document.removeEventListener('click', handleClick)
- }
- }, [ref])
+const SelectCommon = ({ type = 'default', size = 'base', option, placeholder, onChange}: Props) => {
+ const [selectedName, setSelectedName] = useState(placeholder)
+ const [selectedValue, setSelectedValue] = useState('')
- const changeActiveStatus = () => {
- setActive(!isActive)
- }
-
- const changeSelectedName = (item:string) => {
+ const changeSelectedName = (item:string, value: string) => {
+ setSelectedValue(value)
setSelectedName(item)
+ onChange && onChange(value)
}
return(
<>
@@ -45,29 +27,29 @@ const SelectCommon = ({ type = 'default', size = 'base', option, children }: Pro
[s.select] : true,
[s[size]] : !!size,
[s[type]] : !!type,
- [s.isActive] : isActive,
})}
- onClick = { changeActiveStatus }
- ref = {ref}
>
{selectedName}
-
-
- {
- option.map(item =>
-
- )
- }
+
+
+
+ {
+ option.map(item =>
+
+ )
+ }
+
+
>
)
diff --git a/src/components/common/SelectCommon/SelectOption/SelectOption.module.scss b/src/components/common/SelectCommon/SelectOption/SelectOption.module.scss
index 5448f9879..ef504c112 100644
--- a/src/components/common/SelectCommon/SelectOption/SelectOption.module.scss
+++ b/src/components/common/SelectCommon/SelectOption/SelectOption.module.scss
@@ -13,5 +13,9 @@
}
&:hover{
background-color: var(--gray);
+ color: var(--primary);
+ }
+ &.isChoose{
+ background-color: var(--gray);
}
}
\ No newline at end of file
diff --git a/src/components/common/SelectCommon/SelectOption/SelectOption.tsx b/src/components/common/SelectCommon/SelectOption/SelectOption.tsx
index 54877d5fe..7e1968f9e 100644
--- a/src/components/common/SelectCommon/SelectOption/SelectOption.tsx
+++ b/src/components/common/SelectCommon/SelectOption/SelectOption.tsx
@@ -2,20 +2,22 @@ import s from './SelectOption.module.scss'
import classNames from 'classnames'
interface Props{
- onClick: (value: string) => void,
+ onClick: (name: string, value: string) => void,
itemName: string,
size: 'base' | 'large',
+ value: string,
+ selected?: boolean,
}
-const SelectOption = ({onClick, itemName, size}: Props) => {
-
+const SelectOption = ({onClick, itemName, size, value, selected} : Props) => {
const changeName = () => {
- onClick(itemName)
+ onClick(itemName, value)
}
return(
{itemName}
diff --git a/src/components/common/index.ts b/src/components/common/index.ts
index d10f17f8c..e04566de9 100644
--- a/src/components/common/index.ts
+++ b/src/components/common/index.ts
@@ -30,6 +30,7 @@ export { default as SelectCommon} from './SelectCommon/SelectCommon'
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 CardBlog} from './CardBlog/CardBlog'
export { default as RelevantBlogPosts} from './RelevantBlogPosts/RelevantBlogPosts'
diff --git a/src/components/icons/ArrowLeftSmall.tsx b/src/components/icons/ArrowLeftSmall.tsx
new file mode 100644
index 000000000..7bb82665d
--- /dev/null
+++ b/src/components/icons/ArrowLeftSmall.tsx
@@ -0,0 +1,18 @@
+const ArrowLeft = ({ ...props }) => {
+ return (
+
+
+
+ )
+}
+
+export default ArrowLeft
diff --git a/src/components/icons/ArrowRightSmall.tsx b/src/components/icons/ArrowRightSmall.tsx
new file mode 100644
index 000000000..36b4cd589
--- /dev/null
+++ b/src/components/icons/ArrowRightSmall.tsx
@@ -0,0 +1,18 @@
+const ArrowRight = ({ ...props }) => {
+ return (
+
+
+
+ )
+}
+
+export default ArrowRight
diff --git a/src/components/icons/IconArrowUp.tsx b/src/components/icons/IconArrowUp.tsx
index 3eac6391b..1f518d612 100644
--- a/src/components/icons/IconArrowUp.tsx
+++ b/src/components/icons/IconArrowUp.tsx
@@ -2,7 +2,7 @@ const ArrowUp = () => {
return (
-
+
)
}
diff --git a/src/components/icons/IconHide.tsx b/src/components/icons/IconHide.tsx
new file mode 100644
index 000000000..a977aff84
--- /dev/null
+++ b/src/components/icons/IconHide.tsx
@@ -0,0 +1,12 @@
+import React from 'react'
+
+const IconHide = () => {
+ return (
+
+
+
+
+ )
+}
+
+export default IconHide
diff --git a/src/components/icons/IconVectorDown.tsx b/src/components/icons/IconVectorDown.tsx
index 019fc2806..0bb1cb8c1 100644
--- a/src/components/icons/IconVectorDown.tsx
+++ b/src/components/icons/IconVectorDown.tsx
@@ -1,5 +1,3 @@
-
-
const IconVectorDown = ({ ...props }) => {
return (
div {
+ @apply w-full h-full custom-border-radius-lg;
+ }
+ img {
+ object-fit: cover;
+ }
+ }
.text {
@apply relative font-heading text-center;
diff --git a/src/components/modules/home/HomeBanner/HomeBanner.tsx b/src/components/modules/home/HomeBanner/HomeBanner.tsx
index 2a3a632fb..18432ec82 100644
--- a/src/components/modules/home/HomeBanner/HomeBanner.tsx
+++ b/src/components/modules/home/HomeBanner/HomeBanner.tsx
@@ -1,8 +1,9 @@
import React from 'react'
import { Banner } from 'src/components/common'
-import s from './HomeBanner.module.scss'
import BannerImgRight from './assets/banner_full.png'
-import BannerImgRight2 from './assets/banner_product.png'
+import HomeBannerImg from './assets/home_banner.png'
+import s from './HomeBanner.module.scss'
+import Image from 'next/image'
interface Props {
className?: string
@@ -13,6 +14,9 @@ const HomeBanner = ({ }: Props) => {
return (
+
+
+
Freshness guaranteed
@@ -28,10 +32,10 @@ const HomeBanner = ({ }: Props) => {
{
title: "Save 15% on your first order 2",
subtitle: "Last call! Shop deep deals on 100+ bulk picks while you can.",
- imgLink: BannerImgRight2.src,
+ imgLink: BannerImgRight.src,
size: "small",
}
- ]
+ ]
}
/>
diff --git a/src/components/modules/home/HomeBanner/assets/banner_product.png b/src/components/modules/home/HomeBanner/assets/banner_product.png
deleted file mode 100644
index 82f1b7fee..000000000
Binary files a/src/components/modules/home/HomeBanner/assets/banner_product.png and /dev/null differ
diff --git a/src/components/modules/home/HomeVideo/assets/bg_left.svg b/src/components/modules/home/HomeVideo/assets/bg_left.svg
index d730f777d..74b215ae0 100644
--- a/src/components/modules/home/HomeVideo/assets/bg_left.svg
+++ b/src/components/modules/home/HomeVideo/assets/bg_left.svg
@@ -1,19 +1,19 @@
-
-
+
+
-
-
+
+
-
-
+
+
diff --git a/src/components/modules/home/HomeVideo/assets/bg_right.svg b/src/components/modules/home/HomeVideo/assets/bg_right.svg
index e89652a3a..346d14e31 100644
--- a/src/components/modules/home/HomeVideo/assets/bg_right.svg
+++ b/src/components/modules/home/HomeVideo/assets/bg_right.svg
@@ -1,21 +1,21 @@
-
-
+
+
-
-
+
+
-
-
+
+
diff --git a/src/styles/_utilities.scss b/src/styles/_utilities.scss
index cc13ea3cf..6b919de76 100644
--- a/src/styles/_utilities.scss
+++ b/src/styles/_utilities.scss
@@ -149,6 +149,7 @@
.line {
@apply flex justify-between items-center;
> div {
+ flex: 1;
&:not(:last-child) {
margin-right: 1.6rem;
}
diff --git a/src/utils/constanst.utils.ts b/src/utils/constanst.utils.ts
index a2ccb73f4..1522e477f 100644
--- a/src/utils/constanst.utils.ts
+++ b/src/utils/constanst.utils.ts
@@ -33,7 +33,9 @@ export const QUERY_KEY = {
TAB: 'tab',
CATEGORY: 'category',
BRAND: 'brand',
- FEATURED: 'feature'
+ FEATURED: 'feature',
+ SORTBY:'sortby',
+ RECIPES:'recipes'
}
export enum ProductFeature {
@@ -47,3 +49,5 @@ export const KEY = {
ENTER: 'Enter',
}
+export const OPTION_ALL = 'all';
+export const DEFAULT_PAGE_SIZE=20
\ No newline at end of file
diff --git a/src/utils/language.utils.ts b/src/utils/language.utils.ts
index 191215aaa..8b3d8f8d5 100644
--- a/src/utils/language.utils.ts
+++ b/src/utils/language.utils.ts
@@ -2,6 +2,7 @@ export const LANGUAGE = {
BUTTON_LABEL: {
BUY_NOW: 'Buy now',
SHOP_NOW: 'Shop now',
+ CONFIRM:'Confirm',
ADD_TO_CARD: 'Add to Cart',
PREORDER: 'Pre-Order Now',
},
diff --git a/src/utils/types.utils.ts b/src/utils/types.utils.ts
index c87305f2b..d6f1b47ad 100644
--- a/src/utils/types.utils.ts
+++ b/src/utils/types.utils.ts
@@ -24,4 +24,11 @@ export interface RecipeProps {
imageSrc: string
}
+export interface BlogProps {
+ title: string
+ slug: string
+ description: string
+ imageSrc: string
+}
+
export type MouseAndTouchEvent = MouseEvent | TouchEvent
\ No newline at end of file