feat: cart drawer context

:%s
This commit is contained in:
lytrankieio123
2021-09-22 14:56:33 +07:00
parent 11a5de57f8
commit 7ac30b61d3
8 changed files with 137 additions and 67 deletions

View File

@@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { useCartDrawer } from 'src/components/contexts/CartDrawer/CartDrawerContext';
import { PRODUCT_CART_DATA_TEST } from 'src/utils/demo-data'; import { PRODUCT_CART_DATA_TEST } from 'src/utils/demo-data';
import { DrawerCommon } from '..'; import { DrawerCommon } from '..';
import s from './CartDrawer.module.scss'; import s from './CartDrawer.module.scss';
@@ -8,24 +9,24 @@ import CartRecommendation from './components/CartRecommendation/CartRecommendati
import ProductsInCart from './components/ProductsInCart/ProductsInCart'; import ProductsInCart from './components/ProductsInCart/ProductsInCart';
interface Props { interface Props {
visible: boolean
onClose: () => void
} }
const CartDrawer = ({ visible, onClose }: Props) => { const CartDrawer = ({ }: Props) => {
const { cartVisible, closeCartDrawer } = useCartDrawer()
return ( return (
<DrawerCommon <DrawerCommon
title={`Your cart (${PRODUCT_CART_DATA_TEST.length})`} title={`Your cart (${PRODUCT_CART_DATA_TEST.length})`}
visible={visible} visible={cartVisible}
onClose={onClose}> onClose={closeCartDrawer}>
<div className={s.cartDrawer}> <div className={s.cartDrawer}>
<div className={s.body}> <div className={s.body}>
<ProductsInCart data={PRODUCT_CART_DATA_TEST}/> <ProductsInCart data={PRODUCT_CART_DATA_TEST} />
<CartRecommendation /> <CartRecommendation />
</div> </div>
<div> <div>
<CartMessage /> <CartMessage />
<CartCheckoutButton onClose={onClose}/> <CartCheckoutButton onClose={closeCartDrawer} />
</div> </div>
</div> </div>
</DrawerCommon> </DrawerCommon>

View File

@@ -19,15 +19,6 @@ const Header = memo(({ toggleFilter, visibleFilter }: props) => {
const [isFullHeader, setIsFullHeader] = useState<boolean>(true) const [isFullHeader, setIsFullHeader] = useState<boolean>(true)
const { visible: visibleModalAuthen, closeModal: closeModalAuthen, openModal: openModalAuthen } = useModalCommon({ initialValue: false }) const { visible: visibleModalAuthen, closeModal: closeModalAuthen, openModal: openModalAuthen } = useModalCommon({ initialValue: false })
const { visible: visibleModalInfo, closeModal: closeModalInfo, openModal: openModalInfo } = useModalCommon({ initialValue: false }) const { visible: visibleModalInfo, closeModal: closeModalInfo, openModal: openModalInfo } = useModalCommon({ initialValue: false })
const { visible: visibleCartDrawer, openModal: openCartDrawer, closeModal: closeCartDrawer } = useModalCommon({ initialValue: false })
const toggleCart = () => {
if (visibleCartDrawer) {
closeCartDrawer()
} else {
openCartDrawer()
}
}
useEffect(() => { useEffect(() => {
const handleScroll = () => { const handleScroll = () => {
@@ -36,10 +27,6 @@ const Header = memo(({ toggleFilter, visibleFilter }: props) => {
} else { } else {
setIsFullHeader(true) setIsFullHeader(true)
} }
// if (!isMobile()) {
// } else {
// setIsFullHeader(true)
// }
} }
window.addEventListener('scroll', handleScroll) window.addEventListener('scroll', handleScroll)
return () => { return () => {
@@ -56,7 +43,6 @@ const Header = memo(({ toggleFilter, visibleFilter }: props) => {
<HeaderMenu <HeaderMenu
isStickyHeader={true} isStickyHeader={true}
toggleFilter={toggleFilter} toggleFilter={toggleFilter}
toggleCart={toggleCart}
openModalAuthen={openModalAuthen} openModalAuthen={openModalAuthen}
openModalInfo={openModalInfo} /> openModalInfo={openModalInfo} />
</div> </div>
@@ -68,7 +54,6 @@ const Header = memo(({ toggleFilter, visibleFilter }: props) => {
isFull={isFullHeader} isFull={isFullHeader}
visibleFilter={visibleFilter} visibleFilter={visibleFilter}
toggleFilter={toggleFilter} toggleFilter={toggleFilter}
toggleCart={toggleCart}
openModalAuthen={openModalAuthen} openModalAuthen={openModalAuthen}
openModalInfo={openModalInfo} /> openModalInfo={openModalInfo} />
<HeaderSubMenu /> <HeaderSubMenu />
@@ -78,9 +63,7 @@ const Header = memo(({ toggleFilter, visibleFilter }: props) => {
<HeaderSubMenuMobile /> <HeaderSubMenuMobile />
<ModalAuthenticate visible={visibleModalAuthen} closeModal={closeModalAuthen} /> <ModalAuthenticate visible={visibleModalAuthen} closeModal={closeModalAuthen} />
<ModalCreateUserInfo demoVisible={visibleModalInfo} demoCloseModal={closeModalInfo} /> <ModalCreateUserInfo demoVisible={visibleModalInfo} demoCloseModal={closeModalInfo} />
<CartDrawer
visible={visibleCartDrawer}
onClose={closeCartDrawer} />
</> </>
) )
}) })

View File

@@ -5,6 +5,7 @@ import { memo, useMemo } from 'react'
import { ButtonCommon } from 'src/components/common' 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 { useCartDrawer } from 'src/components/contexts/CartDrawer/CartDrawerContext'
import { IconBuy, IconFilter, IconHeart, IconHistory, IconUser } from 'src/components/icons' import { IconBuy, IconFilter, IconHeart, IconHistory, IconUser } from 'src/components/icons'
import { ACCOUNT_TAB, FILTER_PAGE, 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'
@@ -17,13 +18,12 @@ interface Props {
openModalAuthen: () => void, openModalAuthen: () => void,
openModalInfo: () => void, openModalInfo: () => void,
toggleFilter: () => void, toggleFilter: () => void,
toggleCart: () => void,
} }
const HeaderMenu = memo(({ isFull, isStickyHeader, visibleFilter, openModalAuthen, openModalInfo, toggleFilter, toggleCart }: Props) => { const HeaderMenu = memo(({ isFull, isStickyHeader, visibleFilter, openModalAuthen, openModalInfo, toggleFilter }: Props) => {
const router = useRouter() const router = useRouter()
const { toggleCartDrawer } = useCartDrawer()
const optionMenu = useMemo(() => [ const optionMenu = useMemo(() => [
{ {
@@ -74,7 +74,7 @@ const HeaderMenu = memo(({ isFull, isStickyHeader, visibleFilter, openModalAuthe
</button> </button>
) )
} }
<button className={`${s.iconCart} ${s.btnCart}`} onClick={toggleCart}> <button className={`${s.iconCart} ${s.btnCart}`} onClick={toggleCartDrawer}>
<IconBuy /> <IconBuy />
</button> </button>
</div> </div>
@@ -108,7 +108,7 @@ const HeaderMenu = memo(({ isFull, isStickyHeader, visibleFilter, openModalAuthe
<MenuDropdown options={optionMenu} isHasArrow={false}><IconUser /></MenuDropdown> <MenuDropdown options={optionMenu} isHasArrow={false}><IconUser /></MenuDropdown>
</li> </li>
<li> <li>
<button className={s.btnCart} onClick={toggleCart}> <button className={s.btnCart} onClick={toggleCartDrawer}>
<IconBuy /> <IconBuy />
</button> </button>
</li> </li>

View File

@@ -1,14 +1,8 @@
import { CommerceProvider } from '@framework' 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 { CartDrawerProvider } from 'src/components/contexts/CartDrawer/CartDrawerProvider'
import { BRAND, CATEGORY, FEATURED, FILTER_PAGE, ROUTE } from 'src/utils/constanst.utils' import LayoutContent from './LayoutContent/LayoutContent'
import { ScrollToTop } from '..'
import Footer from '../Footer/Footer'
import Header from '../Header/Header'
import MenuNavigationProductList from '../MenuNavigationProductList/MenuNavigationProductList'
import s from './Layout.module.scss'
interface Props { interface Props {
className?: string className?: string
children?: any children?: any
@@ -16,37 +10,14 @@ interface Props {
// note: demo code // note: demo code
const Layout: FC<Props> = ({ children }) => { const Layout: FC<Props> = ({ children }) => {
const { locale = 'en-US', pathname } = useRouter() const { locale = 'en-US' } = useRouter()
const { visible: visibleFilter, openModal: openFilter, closeModal: closeFilter } = useModalCommon({ initialValue: false })
const router = useRouter()
const toggleFilter = () => {
if (visibleFilter) {
closeFilter()
} else {
openFilter()
}
}
return ( return (
<CommerceProvider locale={locale}> <CommerceProvider locale={locale}>
<div className={s.mainLayout}> <CartDrawerProvider>
<Header toggleFilter={toggleFilter} visibleFilter={visibleFilter} /> <LayoutContent>
{ {children}
router.pathname === ROUTE.ACCOUNT ? </LayoutContent>
<section className={s.wrapperWithBg}> </CartDrawerProvider>
<main>{children}</main>
</section> :
<main>{children}</main>
}
<div className={s.filter}><MenuNavigationProductList categories={CATEGORY} brands={BRAND} featured={FEATURED} visible={visibleFilter} onClose={closeFilter} /> </div>
<ScrollToTop visibilityHeight={1500} />
{
FILTER_PAGE.includes(pathname) && (<div className={s.filter}><MenuNavigationProductList categories={CATEGORY} brands={BRAND} featured={FEATURED} visible={visibleFilter} onClose={closeFilter}/> </div>)
}
<Footer />
</div>
</CommerceProvider> </CommerceProvider>
) )

View File

@@ -0,0 +1,53 @@
import { useRouter } from 'next/router'
import { FC } from 'react'
import { useCartDrawer } from 'src/components/contexts/CartDrawer/CartDrawerContext'
import { useModalCommon } from 'src/components/hooks'
import { BRAND, CATEGORY, FEATURED, FILTER_PAGE, ROUTE } from 'src/utils/constanst.utils'
import { CartDrawer, Footer, ScrollToTop } from '../..'
import Header from '../../Header/Header'
import MenuNavigationProductList from '../../MenuNavigationProductList/MenuNavigationProductList'
import s from './LayoutContent.module.scss'
interface Props {
className?: string
children?: any
}
const LayoutContent: FC<Props> = ({ children }) => {
const { pathname } = useRouter()
const { visible: visibleFilter, openModal: openFilter, closeModal: closeFilter } = useModalCommon({ initialValue: false })
const router = useRouter()
const toggleFilter = () => {
if (visibleFilter) {
closeFilter()
} else {
openFilter()
}
}
return (
<>
<div className={s.mainLayout}>
<Header toggleFilter={toggleFilter} visibleFilter={visibleFilter} />
{
router.pathname === ROUTE.ACCOUNT ?
<section className={s.wrapperWithBg}>
<main>{children}</main>
</section> :
<main>{children}</main>
}
<div className={s.filter}><MenuNavigationProductList categories={CATEGORY} brands={BRAND} featured={FEATURED} visible={visibleFilter} onClose={closeFilter} /> </div>
<ScrollToTop visibilityHeight={1500} />
{
FILTER_PAGE.includes(pathname) && (<div className={s.filter}><MenuNavigationProductList categories={CATEGORY} brands={BRAND} featured={FEATURED} visible={visibleFilter} onClose={closeFilter} /> </div>)
}
<Footer />
</div>
<CartDrawer />
</>
)
}
export default LayoutContent

View File

@@ -0,0 +1,20 @@
import { createContext, useContext } from 'react';
export type CartDrawerContextType = {
cartVisible: boolean;
toggleCartDrawer: (visible?: boolean) => void;
openCartDrawer: () => void;
closeCartDrawer: () => void;
};
export const DEFAULT_CART_DRAWER_CONTEXT: CartDrawerContextType = {
cartVisible: false,
toggleCartDrawer: () => { },
openCartDrawer: () => { },
closeCartDrawer: () => { },
};
export const CartDrawerContext = createContext<CartDrawerContextType>(DEFAULT_CART_DRAWER_CONTEXT)
export function useCartDrawer() {
return useContext(CartDrawerContext);
}

View File

@@ -0,0 +1,42 @@
import { ReactNode, useEffect, useState } from "react";
import { CartDrawerContext } from "./CartDrawerContext";
type Props = {
children: ReactNode;
};
export function CartDrawerProvider({ children }: Props) {
const [visible, setVisible] = useState<boolean>(false);
useEffect(() => {
const bodyElement = document.getElementsByTagName('body')[0]
if (bodyElement) {
if (visible) {
bodyElement.style.overflow = 'hidden'
} else {
bodyElement.style.overflow = 'auto'
bodyElement.removeAttribute('scroll')
}
}
}, [visible])
const closeCartDrawer = () => {
setVisible(false);
};
const openCartDrawer = () => {
setVisible(true);
};
const toggleCartDrawer = () => {
setVisible(!visible);
};
return (
<>
<CartDrawerContext.Provider value={{cartVisible: visible, closeCartDrawer, openCartDrawer, toggleCartDrawer}}>
{children}
</CartDrawerContext.Provider>
</>
);
}