diff --git a/next-env.d.ts b/next-env.d.ts index c6643fda1..9bc3dd46b 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,3 +1,6 @@ /// /// /// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/pages/_error.tsx b/pages/_error.tsx new file mode 100644 index 000000000..545d7e7ed --- /dev/null +++ b/pages/_error.tsx @@ -0,0 +1,9 @@ +import { Layout } from 'src/components/common' +import { ErrorContent } from 'src/components/modules/error-page' + +export default function NotFound() { + return ( + + ) +} +NotFound.Layout = Layout diff --git a/pages/test.tsx b/pages/test.tsx index 0ec1c8136..a16ef6ed1 100644 --- a/pages/test.tsx +++ b/pages/test.tsx @@ -6,6 +6,7 @@ import MenuNavigationProductList from 'src/components/common/MenuNavigationProdu // import { RecipeListPage } from 'src/components/modules/recipes'; import { OPTION_ALL, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils'; import { useModalCommon } from 'src/components/hooks'; + const CATEGORY = [ { name: 'All', @@ -33,7 +34,6 @@ const CATEGORY = [ }, ] const BRAND = [ - { name: 'Maggi', link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=veggie`, @@ -67,15 +67,14 @@ const FEATURED = [ link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=viewed`, } ]; + + +import CheckoutSuccess from 'src/components/modules/checkout/CheckoutSuccess/CheckoutSuccess' +import LoadingCommon from 'src/components/common/LoadingCommon/LoadingCommon' +import SkeletonParagraph from 'src/components/common/SkeletonCommon/SkeletonParagraph/SkeletonParagraph' +import SkeletonImage from 'src/components/common/SkeletonCommon/SkeletonImage/SkeletonImage' + export default function Test() { - const { visible: visibleMenuFilter, openModal, closeModal: closeMenuFilter } = useModalCommon({ initialValue: false }) - const toggle = () => { - if (visibleMenuFilter) { - closeMenuFilter() - } else { - openModal() - } -} return ( <>
diff --git a/src/components/common/Banner/Banner.tsx b/src/components/common/Banner/Banner.tsx index 9b6b1099a..410fded77 100644 --- a/src/components/common/Banner/Banner.tsx +++ b/src/components/common/Banner/Banner.tsx @@ -8,7 +8,7 @@ interface Props { const option = { slidesPerView: 1, - breakpoints: {} + mode: 'free', } const Banner = memo(({ data }: Props) => { if (data.length === 1) { diff --git a/src/components/common/Header/Header.module.scss b/src/components/common/Header/Header.module.scss index 99cd29fe0..1a73bbae5 100644 --- a/src/components/common/Header/Header.module.scss +++ b/src/components/common/Header/Header.module.scss @@ -6,20 +6,28 @@ left: 0; z-index: 9999; margin-bottom: 3.2rem; - @screen md { - @apply relative; - } + &.full { @apply shadow-none; - border: 1px solid var(--border-line); } .menu { + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); padding-left: 3.2rem; padding-right: 3.2rem; } .logo { @apply font-logo; } + + @screen md { + @apply relative; + &.full { + border: 1px solid var(--border-line); + } + .menu { + @apply shadow-none; + } + } } .headerSticky { diff --git a/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx b/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx index 47d4beb74..4487fa83c 100644 --- a/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx +++ b/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx @@ -1,4 +1,3 @@ -import classNames from 'classnames' import Link from 'next/link' import { useRouter } from 'next/router' import { memo, useMemo } from 'react' @@ -37,6 +36,10 @@ const HeaderMenu = memo(({ visibleFilter,openModalAuthen, openModalInfo, toggleF link: '/account-not-login', name: 'Account Not Login', }, + { + link: ROUTE.NOTIFICATION, + name: 'Notifications', + }, { link: ROUTE.ACCOUNT, name: 'Account', diff --git a/src/components/common/Header/components/HeaderSubMenuMobile/HeaderSubMenuMobile.tsx b/src/components/common/Header/components/HeaderSubMenuMobile/HeaderSubMenuMobile.tsx index ee15ac2cf..7537f7b8e 100644 --- a/src/components/common/Header/components/HeaderSubMenuMobile/HeaderSubMenuMobile.tsx +++ b/src/components/common/Header/components/HeaderSubMenuMobile/HeaderSubMenuMobile.tsx @@ -25,7 +25,7 @@ const OPTION_MENU = [ isMarked: false, }, { - link: `${ROUTE.ACCOUNT}?${QUERY_KEY.TAB}=${ACCOUNT_TAB.NOTIFICATION}`, + link: ROUTE.NOTIFICATION, name: 'Notifications', icon: , isMarked: true, diff --git a/src/components/common/Layout/Layout.tsx b/src/components/common/Layout/Layout.tsx index 4b8803291..76ea316b4 100644 --- a/src/components/common/Layout/Layout.tsx +++ b/src/components/common/Layout/Layout.tsx @@ -3,7 +3,7 @@ import { useRouter } from 'next/router' import { FC } from 'react' import { useModalCommon } from 'src/components/hooks' import { BRAND, CATEGORY, FEATURED } from 'src/utils/constanst.utils' -import { CustomShapeSvg } from '..' +import { CustomShapeSvg, ScrollToTop } from '..' import Footer from '../Footer/Footer' import Header from '../Header/Header' import MenuNavigationProductList from '../MenuNavigationProductList/MenuNavigationProductList' @@ -18,7 +18,7 @@ interface Props { const Layout: FC = ({ children }) => { const { locale = 'en-US' } = useRouter() const { visible: visibleFilter, openModal: openFilter, closeModal: closeFilter } = useModalCommon({ initialValue: false }) - + const toggleFilter = () => { if (visibleFilter) { closeFilter() @@ -34,6 +34,7 @@ const Layout: FC = ({ children }) => {
+
diff --git a/src/components/common/LoadingCommon/LoadingCommon.module.scss b/src/components/common/LoadingCommon/LoadingCommon.module.scss new file mode 100644 index 000000000..f17d4aa9c --- /dev/null +++ b/src/components/common/LoadingCommon/LoadingCommon.module.scss @@ -0,0 +1,24 @@ +@import '../../../styles/utilities'; + +.wrapper { + @apply text-center; + + .loadingCommon { + @apply bg-white; + height: 7rem; + width: 7rem; + animation: spin 2s linear infinite; + margin: auto; + background: url('./assets/carrot.png') top 50% left 50% no-repeat; + } + + .text { + @apply font-bold; + color: var(--primary); + } +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} \ No newline at end of file diff --git a/src/components/common/LoadingCommon/LoadingCommon.tsx b/src/components/common/LoadingCommon/LoadingCommon.tsx new file mode 100644 index 000000000..1e8ffe340 --- /dev/null +++ b/src/components/common/LoadingCommon/LoadingCommon.tsx @@ -0,0 +1,15 @@ +import React from "react"; +import s from './LoadingCommon.module.scss' + +const LoadingCommon = () => { + + return ( +
+
+
+

Loading...

+
+ ) +} + +export default LoadingCommon \ No newline at end of file diff --git a/src/components/common/LoadingCommon/assets/carrot.png b/src/components/common/LoadingCommon/assets/carrot.png new file mode 100644 index 000000000..60a89d625 Binary files /dev/null and b/src/components/common/LoadingCommon/assets/carrot.png differ diff --git a/src/components/common/ScrollToTop/ScrollToTop.module.scss b/src/components/common/ScrollToTop/ScrollToTop.module.scss index c010f08ad..940bc0ac2 100644 --- a/src/components/common/ScrollToTop/ScrollToTop.module.scss +++ b/src/components/common/ScrollToTop/ScrollToTop.module.scss @@ -1,24 +1,24 @@ -@import '../../../styles/utilities'; +@import "../../../styles/utilities"; .scrollToTop { @apply hidden; + z-index: 9999; @screen md { &.show { @apply block rounded-lg fixed cursor-pointer; - right: 11.2rem; - bottom: 21.6rem; + right: 6.4rem; + bottom: 21.6rem; width: 6.4rem; height: 6.4rem; background-color: var(--border-line); - } - - &.hide { - @apply hidden; + @screen lg { + right: 11.2rem; + } } } .scrollToTopBtn { @apply outline-none w-full h-full; } -} \ No newline at end of file +} diff --git a/src/components/common/ScrollToTop/ScrollToTop.tsx b/src/components/common/ScrollToTop/ScrollToTop.tsx index d148c8937..388fae3cc 100644 --- a/src/components/common/ScrollToTop/ScrollToTop.tsx +++ b/src/components/common/ScrollToTop/ScrollToTop.tsx @@ -1,47 +1,44 @@ -import React, { useState, useEffect, MutableRefObject } from 'react' import classNames from 'classnames' +import React, { useEffect, useState } from 'react' +import ArrowUp from '../../icons/IconArrowUp' import s from './ScrollToTop.module.scss' -import ArrowUp from '../../icons/IconArrowUp' interface ScrollToTopProps { visibilityHeight?: number; } -const ScrollToTop = ({ visibilityHeight=450 }: ScrollToTopProps) => { - - const [scrollPosition, setSrollPosition] = useState(0); - const [showScrollToTop, setShowScrollToTop] = useState("hide"); +const ScrollToTop = ({ visibilityHeight = 450 }: ScrollToTopProps) => { + const [showScrollToTop, setShowScrollToTop] = useState(); function handleVisibleButton() { - const position = window.pageYOffset; - setSrollPosition(position); - + const scrollPosition = window.scrollY; + if (scrollPosition > visibilityHeight) { - return setShowScrollToTop("show") - } else if (scrollPosition < visibilityHeight) { - return setShowScrollToTop("hide"); + setShowScrollToTop(true) + } else { + setShowScrollToTop(false) } }; + useEffect(() => { + window.addEventListener("scroll", handleVisibleButton); + return () => { + window.removeEventListener("scroll", handleVisibleButton); + } + }, []); + + function handleScrollUp() { window.scrollTo(0, 0); } - function addEventScroll() { - window.addEventListener("scroll", handleVisibleButton); - } - - useEffect(() => { - addEventScroll(); - }); - return (
+ [s.show]: showScrollToTop + })} + onClick={handleScrollUp} + > diff --git a/src/components/common/SkeletonCommon/SkeletonImage/SkeletonImage.module.scss b/src/components/common/SkeletonCommon/SkeletonImage/SkeletonImage.module.scss new file mode 100644 index 000000000..d9607adec --- /dev/null +++ b/src/components/common/SkeletonCommon/SkeletonImage/SkeletonImage.module.scss @@ -0,0 +1,53 @@ +@import '../../../../styles/utilities'; + +.skeletonImage { + @apply relative; + background: #DDDBDD; + + &.small { + width: 10rem; + height: 10rem; + } + + &.default { + width: 15rem; + height: 15rem; + } + + &.large { + width: 20rem; + height: 20rem; + } + + &.left { + margin-left: 0; + } + + &.center { + margin: auto; + } + + &::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + transform: translateX(-100%); + background-image: linear-gradient( + 90deg, + rgba(#fff, 0) 0, + rgba(#fff, 0.2) 20%, + rgba(#fff, 0.5) 60%, + rgba(#fff, 0) + ); + animation: shimmer 2s infinite; + content: ''; + } +} + +@keyframes shimmer { + 100% { + transform: translateX(100%); + } +} diff --git a/src/components/common/SkeletonCommon/SkeletonImage/SkeletonImage.tsx b/src/components/common/SkeletonCommon/SkeletonImage/SkeletonImage.tsx new file mode 100644 index 000000000..e2c7c5e0f --- /dev/null +++ b/src/components/common/SkeletonCommon/SkeletonImage/SkeletonImage.tsx @@ -0,0 +1,20 @@ +import classNames from "classnames"; +import React from "react"; +import s from './SkeletonImage.module.scss' + +interface SkeletonImageProps { + align?: "left" | "center" + size?: "small" | "default" | "large" +} + +const SkeletonImage = ({ align="center", size="default" }: SkeletonImageProps) => { + return ( +
+
+ ) +} + +export default SkeletonImage \ No newline at end of file diff --git a/src/components/common/SkeletonCommon/SkeletonParagraph/SkeletonParagraph.module.scss b/src/components/common/SkeletonCommon/SkeletonParagraph/SkeletonParagraph.module.scss new file mode 100644 index 000000000..1ebd6e413 --- /dev/null +++ b/src/components/common/SkeletonCommon/SkeletonParagraph/SkeletonParagraph.module.scss @@ -0,0 +1,65 @@ +@import '../../../../styles/utilities'; + +.skeletonParagraph { + margin: 0 1.6rem; + + .row { + display: inline-block; + height: 2rem; + width: 100%; + position: relative; + overflow: hidden; + background-color: #DDDBDD; + + &::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + transform: translateX(-100%); + background-image: linear-gradient( + 90deg, + rgba(#fff, 0) 0, + rgba(#fff, 0.2) 20%, + rgba(#fff, 0.5) 60%, + rgba(#fff, 0) + ); + animation: shimmer 2s infinite; + content: ''; + } + } + + .lastRow { + display: inline-block; + height: 2rem; + width: 80%; + position: relative; + overflow: hidden; + background-color: #DDDBDD; + + &::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + transform: translateX(-100%); + background-image: linear-gradient( + 90deg, + rgba(#fff, 0) 0, + rgba(#fff, 0.2) 20%, + rgba(#fff, 0.5) 60%, + rgba(#fff, 0) + ); + animation: shimmer 2s infinite; + content: ''; + } + } +} + +@keyframes shimmer { + 100% { + transform: translateX(100%); + } +} diff --git a/src/components/common/SkeletonCommon/SkeletonParagraph/SkeletonParagraph.tsx b/src/components/common/SkeletonCommon/SkeletonParagraph/SkeletonParagraph.tsx new file mode 100644 index 000000000..eadcff724 --- /dev/null +++ b/src/components/common/SkeletonCommon/SkeletonParagraph/SkeletonParagraph.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import s from './SkeletonParagraph.module.scss' + +interface SkeletonParagraphProps { + rows?: number // number of rows in paragraph +} + +const SkeletonParagraph = ({ rows=2 }: SkeletonParagraphProps) => { + return ( +
+ { + [...Array(rows)].map((e, i) => { + if (i === rows-1) { + return
+ } + return
+ }) + } +
+ ) +} + +export default SkeletonParagraph \ No newline at end of file diff --git a/src/components/modules/404/404Page/404Page.module.scss b/src/components/modules/404/404Page/404Page.module.scss index b089a9ad3..f490b4f3a 100644 --- a/src/components/modules/404/404Page/404Page.module.scss +++ b/src/components/modules/404/404Page/404Page.module.scss @@ -6,7 +6,7 @@ background-color: white; .inner{ - height: 100vh; + height: 70vh; .logo{ margin-top: 2rem; } diff --git a/src/components/modules/checkout/CheckoutSuccess/CheckoutSuccess.module.scss b/src/components/modules/checkout/CheckoutSuccess/CheckoutSuccess.module.scss new file mode 100644 index 000000000..c7d4b2859 --- /dev/null +++ b/src/components/modules/checkout/CheckoutSuccess/CheckoutSuccess.module.scss @@ -0,0 +1,38 @@ +@import '../../../../styles/utilities'; + +.checkoutSuccessWrapper { + @apply flex items-center justify-center; + margin-top: -3.2rem; + + .checkoutSuccess { + border-radius: 80% 90% 18% 10% / 20% 10% 27% 20%; + max-width: 77.6rem; + height: fit-content; + background: + url('./assets/veget.png') left 0 top 0 no-repeat, + url('./assets/fish.png') right 0 top 0 no-repeat, + url('./assets/freezeShrimp.png') right 0 bottom 0 no-repeat, + url('./assets/coffeeBean.png') left 0 bottom 0 no-repeat; + background-color: #E3F2E9; + + .checkoutContent { + @apply text-center; + margin: 7.2rem 4.8rem 6.4rem 4.8rem; + + .checkoutMsg { + @apply heading-1 font-heading; + margin-top: 3.2rem; + margin-bottom: 1.6rem; + } + + .checkoutSubMsg { + @apply sub-headline; + margin-bottom: 4rem; + } + + .backToHomeBtn { + @apply flex justify-center; + } + } + } +} \ No newline at end of file diff --git a/src/components/modules/checkout/CheckoutSuccess/CheckoutSuccess.tsx b/src/components/modules/checkout/CheckoutSuccess/CheckoutSuccess.tsx new file mode 100644 index 000000000..277cd5e30 --- /dev/null +++ b/src/components/modules/checkout/CheckoutSuccess/CheckoutSuccess.tsx @@ -0,0 +1,34 @@ +import React from "react"; +import s from './CheckoutSuccess.module.scss'; + +import Link from "next/link"; + +import checkIcon from './assets/checkIcon.png'; + +import { ButtonCommon, StaticImage } from "src/components/common"; +import { IconArrowRight } from "src/components/icons"; + +const CheckoutSuccess = () => { + return ( +
+
+
+ + +
Your purchase has been successed!
+
Last call! Shop deep deals on 100+ bulk picks while you can.
+ + +
+
+
+ ) +} + +export default CheckoutSuccess \ No newline at end of file diff --git a/src/components/modules/checkout/CheckoutSuccess/assets/checkIcon.png b/src/components/modules/checkout/CheckoutSuccess/assets/checkIcon.png new file mode 100644 index 000000000..9d97234fb Binary files /dev/null and b/src/components/modules/checkout/CheckoutSuccess/assets/checkIcon.png differ diff --git a/src/components/modules/checkout/CheckoutSuccess/assets/coffeeBean.png b/src/components/modules/checkout/CheckoutSuccess/assets/coffeeBean.png new file mode 100644 index 000000000..742f30b68 Binary files /dev/null and b/src/components/modules/checkout/CheckoutSuccess/assets/coffeeBean.png differ diff --git a/src/components/modules/checkout/CheckoutSuccess/assets/fish.png b/src/components/modules/checkout/CheckoutSuccess/assets/fish.png new file mode 100644 index 000000000..14f676f64 Binary files /dev/null and b/src/components/modules/checkout/CheckoutSuccess/assets/fish.png differ diff --git a/src/components/modules/checkout/CheckoutSuccess/assets/freezeShrimp.png b/src/components/modules/checkout/CheckoutSuccess/assets/freezeShrimp.png new file mode 100644 index 000000000..5b3a501ac Binary files /dev/null and b/src/components/modules/checkout/CheckoutSuccess/assets/freezeShrimp.png differ diff --git a/src/components/modules/checkout/CheckoutSuccess/assets/veget.png b/src/components/modules/checkout/CheckoutSuccess/assets/veget.png new file mode 100644 index 000000000..83b8f51cc Binary files /dev/null and b/src/components/modules/checkout/CheckoutSuccess/assets/veget.png differ diff --git a/src/components/modules/error/ErrorPage/Errorpage.module.scss b/src/components/modules/error-page/ErrorContent/ErrorContent.module.scss similarity index 97% rename from src/components/modules/error/ErrorPage/Errorpage.module.scss rename to src/components/modules/error-page/ErrorContent/ErrorContent.module.scss index 562a20f8b..379c01c46 100644 --- a/src/components/modules/error/ErrorPage/Errorpage.module.scss +++ b/src/components/modules/error-page/ErrorContent/ErrorContent.module.scss @@ -6,7 +6,7 @@ background-color: white; .inner{ - height: 100vh; + height: 70vh; .logo{ margin-top: 2rem; } diff --git a/src/components/modules/error/ErrorPage/ErrorPage.tsx b/src/components/modules/error-page/ErrorContent/ErrorContent.tsx similarity index 86% rename from src/components/modules/error/ErrorPage/ErrorPage.tsx rename to src/components/modules/error-page/ErrorContent/ErrorContent.tsx index 0e550b766..112f9339c 100644 --- a/src/components/modules/error/ErrorPage/ErrorPage.tsx +++ b/src/components/modules/error-page/ErrorContent/ErrorContent.tsx @@ -1,12 +1,12 @@ import Link from 'next/link'; import React from 'react'; import { ButtonCommon } from 'src/components/common'; -import s from './ErrorPage.module.scss'; +import s from './ErrorContent.module.scss'; interface Props { } -const ErrorPage = ({ }: Props) => { +const ErrorContent = ({ }: Props) => { return (
@@ -26,4 +26,4 @@ const ErrorPage = ({ }: Props) => { ) } -export default ErrorPage +export default ErrorContent diff --git a/src/components/modules/error-page/index.tsx b/src/components/modules/error-page/index.tsx new file mode 100644 index 000000000..3732145a5 --- /dev/null +++ b/src/components/modules/error-page/index.tsx @@ -0,0 +1 @@ +export {default as ErrorContent} from './ErrorContent/ErrorContent'; \ No newline at end of file diff --git a/src/components/modules/error/index.tsx b/src/components/modules/error/index.tsx deleted file mode 100644 index 4fadf1398..000000000 --- a/src/components/modules/error/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export {default as ErrorPage} from './ErrorPage/ErrorPage'; \ No newline at end of file diff --git a/src/components/modules/home/HomeBanner/HomeBanner.module.scss b/src/components/modules/home/HomeBanner/HomeBanner.module.scss index a8b1b1d27..bb65a2549 100644 --- a/src/components/modules/home/HomeBanner/HomeBanner.module.scss +++ b/src/components/modules/home/HomeBanner/HomeBanner.module.scss @@ -31,11 +31,15 @@ width: min-content; color: var(--white); - font-size: 8.8rem; + font-size: 7rem; line-height: 8rem; letter-spacing: -0.03em; font-weight: bold; text-transform: uppercase; + + @screen 2xl { + line-height: 8rem; + } &::after { @apply absolute; content: ""; diff --git a/src/utils/constanst.utils.ts b/src/utils/constanst.utils.ts index e85f5fdee..3d55aac06 100644 --- a/src/utils/constanst.utils.ts +++ b/src/utils/constanst.utils.ts @@ -21,6 +21,7 @@ export const ROUTE = { RECIPES: '/recipes', RECIPE_DETAIL: '/recipe', + NOTIFICATION: '/notifications', BUSSINESS: '/bussiness', CONTACT: '/contact', CHECKOUT: '/checkout', @@ -35,7 +36,6 @@ export const ACCOUNT_TAB = { CUSTOMER_INFO: '', ORDER: 'orders', FAVOURITE: 'wishlist', - NOTIFICATION: 'notification', } export const QUERY_KEY = {