diff options
| author | Rafi Zadanly <rafizadanly@gmail.com> | 2022-11-19 13:55:00 +0700 |
|---|---|---|
| committer | Rafi Zadanly <rafizadanly@gmail.com> | 2022-11-19 13:55:00 +0700 |
| commit | 40bab7be1e0025c7c089e1eac17451ef155a989a (patch) | |
| tree | 5a87f4fd87f3c6bc0823e58614dd93ca6c97d2c8 /src | |
| parent | 679e565b4594bd172f2576926567a740760ff55e (diff) | |
Add page transition
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/Layout.js | 26 | ||||
| -rw-r--r-- | src/pages/_app.js | 25 | ||||
| -rw-r--r-- | src/pages/index.js | 55 | ||||
| -rw-r--r-- | src/pages/shop/brands.js | 5 | ||||
| -rw-r--r-- | src/pages/shop/product/[slug].js | 5 | ||||
| -rw-r--r-- | src/pages/shop/search.js | 5 |
6 files changed, 72 insertions, 49 deletions
diff --git a/src/components/Layout.js b/src/components/Layout.js new file mode 100644 index 00000000..eb4e8923 --- /dev/null +++ b/src/components/Layout.js @@ -0,0 +1,26 @@ +import { motion } from 'framer-motion'; + +export default function Layout({ children, pageProps }) { + const variants = { + hidden: { opacity: 0, x: -75, y: 0 }, + enter: { opacity: 1, x: 0, y: 0 }, + exit: { opacity: 0, x: 0, y: -50 }, + }; + + const transition = { + ease: 'linear', + duration: 0.2 + }; + + return children && ( + <motion.main + initial={{ opacity: 0, x: -75, y: 0 }} + animate={{ opacity: 1, x: 0, y: 0 }} + exit={{ opacity: 0, x: 0, y: -50 }} + transition={transition} + {...pageProps} + > + {children} + </motion.main> + ); +}
\ No newline at end of file diff --git a/src/pages/_app.js b/src/pages/_app.js index db14ca15..faa8b2b4 100644 --- a/src/pages/_app.js +++ b/src/pages/_app.js @@ -1,23 +1,14 @@ import '../styles/globals.css'; -import NextProgress from "next-progress"; +import NextProgress from 'next-progress'; import { ToastContainer, Slide } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; import Image from 'next/image'; +import { AnimatePresence } from 'framer-motion'; function MyApp({ Component, pageProps }) { const router = useRouter(); - const [pageLoading, setPageLoading] = useState(false); - - useEffect(() => { - const handleStartLoading = () => { setPageLoading(true) }; - const handleCompleteLoading = () => { setPageLoading(false) }; - - router.events.on('routeChangeStart', handleStartLoading); - router.events.on('routeChangeComplete', handleCompleteLoading); - router.events.on('routeChangeError', handleCompleteLoading); - }, [router]); return ( <> @@ -32,12 +23,12 @@ function MyApp({ Component, pageProps }) { <NextProgress color="#D7A30A" options={{ showSpinner: false, }} /> - {pageLoading ? ( - <div className='h-screen w-screen flex flex-col justify-center items-center'> - <Image src='/images/loading.gif' width={96} height={96} alt='Loading Indoteknik' /> - <h1>Loading</h1> - </div> - ) : <Component {...pageProps} />} + <AnimatePresence + mode='sync' + initial={false} + > + <Component {...pageProps} /> + </AnimatePresence> </> ) } diff --git a/src/pages/index.js b/src/pages/index.js index 7fa538d1..a0363a62 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -9,6 +9,7 @@ import "swiper/css"; import "swiper/css/pagination"; import "swiper/css/autoplay"; import ProductSlider from "../components/product/ProductSlider"; +import Layout from "../components/Layout"; export default function Home() { const [heroBanners, setHeroBanners] = useState(null); @@ -44,38 +45,40 @@ export default function Home() { return ( <> - <Header title="Home - Indoteknik" /> - <Swiper slidesPerView={1} pagination={{dynamicBullets: true}} modules={[Pagination, Autoplay]}> - { - heroBanners?.map((banner, index) => ( - <SwiperSlide key={index}> - <LazyLoadImage effect="blur" src={banner.image} alt={banner.name} className="w-full h-auto" /> - </SwiperSlide> - )) - } - </Swiper> - <div className="mt-6 px-4"> - <h2 className="text-gray-900 font-bold mb-3">Brand Pilihan</h2> - <Swiper slidesPerView={4} freeMode={true} spaceBetween={16}> + <Header title='Home - Indoteknik' /> + <Layout key='/home'> + <Swiper slidesPerView={1} pagination={{dynamicBullets: true}} modules={[Pagination, Autoplay]}> { - manufactures?.manufactures?.map((manufacture, index) => ( + heroBanners?.map((banner, index) => ( <SwiperSlide key={index}> - <div className="border border-gray-300 p-1 rounded h-full"> - <LazyLoadImage effect="blur" src={manufacture.logo} alt={manufacture.name} className="w-full h-full object-contain object-center" /> - </div> + <LazyLoadImage effect="blur" src={banner.image} alt={banner.name} className="w-full h-auto" /> </SwiperSlide> )) } </Swiper> - </div> - <div className="mt-6 px-4 mb-6"> - <h2 className="text-gray-900 font-bold mb-3">Produk Ready Stock</h2> - <ProductSlider products={readyStockProducts} /> - </div> - <div className="mt-6 px-4 mb-6"> - <h2 className="text-gray-900 font-bold mb-3">Produk Populer</h2> - <ProductSlider products={popularProducts} /> - </div> + <div className="mt-6 px-4"> + <h2 className="text-gray-900 font-bold mb-3">Brand Pilihan</h2> + <Swiper slidesPerView={4} freeMode={true} spaceBetween={16}> + { + manufactures?.manufactures?.map((manufacture, index) => ( + <SwiperSlide key={index}> + <div className="border border-gray-300 p-1 rounded h-full"> + <LazyLoadImage effect="blur" src={manufacture.logo} alt={manufacture.name} className="w-full h-full object-contain object-center" /> + </div> + </SwiperSlide> + )) + } + </Swiper> + </div> + <div className="mt-6 px-4 mb-6"> + <h2 className="text-gray-900 font-bold mb-3">Produk Ready Stock</h2> + <ProductSlider products={readyStockProducts} /> + </div> + <div className="mt-6 px-4 mb-6"> + <h2 className="text-gray-900 font-bold mb-3">Produk Populer</h2> + <ProductSlider products={popularProducts} /> + </div> + </Layout> </> ) } diff --git a/src/pages/shop/brands.js b/src/pages/shop/brands.js index 797843ee..499eaf99 100644 --- a/src/pages/shop/brands.js +++ b/src/pages/shop/brands.js @@ -7,6 +7,7 @@ import { createSlug } from "../../helpers/slug"; import InfiniteScroll from "react-infinite-scroll-component"; import { useState } from "react"; import Spinner from "../../components/Spinner"; +import Layout from "../../components/Layout"; export async function getServerSideProps() { let initialManufactures = await apiOdoo('GET', '/api/v1/manufacture?limit=31'); @@ -25,7 +26,7 @@ export default function Brands({ initialManufactures }) { return ( <> <Header title='Semua Brand di Indoteknik' /> - <main className="p-4"> + <Layout className='p-4' key='/shop/brands'> <h1>Semua Brand di Indoteknik</h1> <InfiniteScroll dataLength={manufactures.length} @@ -48,7 +49,7 @@ export default function Brands({ initialManufactures }) { ) : '' ))} </InfiniteScroll> - </main> + </Layout> </> ) }
\ No newline at end of file diff --git a/src/pages/shop/product/[slug].js b/src/pages/shop/product/[slug].js index a42e6cb9..923962e2 100644 --- a/src/pages/shop/product/[slug].js +++ b/src/pages/shop/product/[slug].js @@ -8,6 +8,7 @@ import currencyFormat from "../../../helpers/currencyFormat"; import { LazyLoadImage } from "react-lazy-load-image-component"; import "react-lazy-load-image-component/src/effects/blur.css"; import ProductSlider from "../../../components/product/ProductSlider"; +import Layout from "../../../components/Layout"; export async function getServerSideProps(context) { const { slug } = context.query; @@ -80,7 +81,7 @@ export default function ProductDetail({product}) { return ( <> <Header title={`${product.name} - Indoteknik`}/> - <main> + <Layout key={`/shop/product/${slug}`}> <LazyLoadImage effect="blur" src={product.image} alt={product.name} className="border-b border-gray-300 w-full h-[300px] object-contain object-center bg-white" /> <div className="p-4 pb-10"> @@ -170,7 +171,7 @@ export default function ProductDetail({product}) { </div> </div> - </main> + </Layout> </> ); }
\ No newline at end of file diff --git a/src/pages/shop/search.js b/src/pages/shop/search.js index ce76f88e..d0917666 100644 --- a/src/pages/shop/search.js +++ b/src/pages/shop/search.js @@ -1,5 +1,6 @@ import axios from "axios"; import Header from "../../components/Header"; +import Layout from "../../components/Layout"; import Pagination from "../../components/Pagination"; import ProductCard from "../../components/ProductCard"; import FilterIcon from "../../icons/filter.svg"; @@ -19,7 +20,7 @@ export default function ShopSearch({ searchResults, q, page }) { return ( <> <Header title={`Jual ${q} - Indoteknik`} /> - <main> + <Layout key={`/shop/search?q=${q}&page=${page}`}> <div className="p-4"> <div className="flex justify-between items-center gap-x-2 mb-1"> <h1>Produk</h1> @@ -54,7 +55,7 @@ export default function ShopSearch({ searchResults, q, page }) { <Pagination pageCount={pageCount} currentPage={parseInt(page)} url={`/shop/search?q=${q}`} /> </div> </div> - </main> + </Layout> </> ) }
\ No newline at end of file |
