├── public ├── hero.jpg ├── hero.png ├── adidas.jpg ├── favicon.ico ├── favicon.png ├── hero.webp └── hero.svg ├── styles ├── test.scss └── theme.js ├── pages ├── shop.js ├── success.js ├── _document.js ├── index.js ├── _app.js ├── cart.js ├── checkout.js └── product │ └── [permalink].js ├── next.config.js ├── README.md ├── lib └── commerce.js ├── jsconfig.json ├── utils └── fetcher.js ├── components ├── DarkModeSwitch.js ├── Footer.js ├── Shipping │ ├── Success.js │ ├── OrderTotal.js │ ├── Payment.js │ └── Shipping.js ├── RelatedProducts.js ├── VariantPicker.js ├── SearchBar.js ├── Hero.js ├── NavBar.js └── Product │ ├── Products.js │ ├── Product.js │ └── ProductButton.js ├── .gitignore ├── package.json ├── LICENSE └── context ├── cart.js └── checkout.js /public/hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarsimranBarki/rapid-store/HEAD/public/hero.jpg -------------------------------------------------------------------------------- /public/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarsimranBarki/rapid-store/HEAD/public/hero.png -------------------------------------------------------------------------------- /styles/test.scss: -------------------------------------------------------------------------------- 1 | .harsimran{ 2 | background-color: 'red'; 3 | color: 'green'; 4 | } -------------------------------------------------------------------------------- /public/adidas.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarsimranBarki/rapid-store/HEAD/public/adidas.jpg -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarsimranBarki/rapid-store/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarsimranBarki/rapid-store/HEAD/public/favicon.png -------------------------------------------------------------------------------- /public/hero.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarsimranBarki/rapid-store/HEAD/public/hero.webp -------------------------------------------------------------------------------- /pages/shop.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | function shop() { 4 | return
; 5 | } 6 | 7 | export default shop; 8 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | const withImages = require("next-images"); 2 | module.exports = withImages({ 3 | images: { 4 | domains: ["cdn.chec.io"], 5 | }, 6 | }); 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rapid Store - Ecommerce Website 2 | 3 | ## Tech Stack 4 | 5 | - Chakra UI 6 | - Next JS 7 | - Ecommerce 8 | - Stripe 9 | 10 | ### Deployed using vercel 11 | -------------------------------------------------------------------------------- /lib/commerce.js: -------------------------------------------------------------------------------- 1 | import CommerceSDK from "@chec/commerce.js"; 2 | 3 | const client = new CommerceSDK(process.env.NEXT_PUBLIC_CHEC_PUBLIC_API_KEY); 4 | 5 | export default client; 6 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "@/components/*": ["components/*"], 6 | "@/lib/*": ["lib/*"], 7 | "@/styles/*": ["styles/*"], 8 | "@/utils/*": ["utils/*"], 9 | "@/context/*": ["context/*"] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /utils/fetcher.js: -------------------------------------------------------------------------------- 1 | const fetcher = async (url, token) => { 2 | const res = await fetch(url, { 3 | method: "GET", 4 | headers: new Headers({ "Content-Type": "application/json", token }), 5 | credentials: "same-origin", 6 | }); 7 | 8 | return res.json(); 9 | }; 10 | 11 | export default fetcher; 12 | -------------------------------------------------------------------------------- /pages/success.js: -------------------------------------------------------------------------------- 1 | import Success from "@/components/Shipping/Success"; 2 | import { Grid } from "@chakra-ui/layout"; 3 | import React from "react"; 4 | 5 | function success() { 6 | return ( 7 | 8 | 9 | 10 | ); 11 | } 12 | 13 | export default success; 14 | -------------------------------------------------------------------------------- /components/DarkModeSwitch.js: -------------------------------------------------------------------------------- 1 | import { useColorMode, Switch } from '@chakra-ui/react' 2 | 3 | export const DarkModeSwitch = () => { 4 | const { colorMode, toggleColorMode } = useColorMode() 5 | const isDark = colorMode === 'dark' 6 | return ( 7 | 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | -------------------------------------------------------------------------------- /components/Footer.js: -------------------------------------------------------------------------------- 1 | import { Box, HStack, Text } from '@chakra-ui/layout' 2 | import React from 'react' 3 | 4 | function Footer() { 5 | return ( 6 | 7 | 8 | Home 9 | About 10 | Shop 11 | Jobs 12 | Partners 13 | 14 | © 2021 Radid Store Inc. All rights reserved 15 | 16 | ) 17 | } 18 | 19 | export default Footer 20 | -------------------------------------------------------------------------------- /pages/_document.js: -------------------------------------------------------------------------------- 1 | import NextDocument, { Html, Head, Main, NextScript } from "next/document"; 2 | import { ColorModeScript } from "@chakra-ui/react"; 3 | import favicon from "public/favicon.png"; 4 | export default class Document extends NextDocument { 5 | render() { 6 | return ( 7 | 8 | 9 | 10 | 11 | 15 | 16 | 17 | {/* Make Color mode to persists when you refresh the page. */} 18 | 19 |
20 | 21 | 22 | 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import Hero from "@/components/Hero"; 2 | import Products from "@/components/Product/Products"; 3 | import commerce from "@/lib/commerce"; 4 | import { motion } from "framer-motion"; 5 | import React from "react"; 6 | 7 | 8 | export async function getStaticProps() { 9 | const merchant = await commerce.merchants.about(); 10 | const { data: categories } = await commerce.categories.list(); 11 | const { data: products } = await commerce.products.list(); 12 | 13 | return { 14 | props: { 15 | merchant, 16 | categories, 17 | products, 18 | }, 19 | }; 20 | } 21 | 22 | const Index = ({ merchant, categories, products }) => { 23 | return ( 24 | 29 | 30 | 31 | 32 | 37 | 38 | 39 | ); 40 | }; 41 | 42 | export default Index; 43 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "with-chakra-ui", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "dev": "next dev", 6 | "build": "next build", 7 | "start": "next start" 8 | }, 9 | "dependencies": { 10 | "@chakra-ui/icons": "^1.0.0", 11 | "@chakra-ui/react": "^1.4.2", 12 | "@chec/commerce.js": "^2.4.1", 13 | "@chec/react-commercejs-hooks": "^0.3.1", 14 | "@emotion/react": "^11.0.0", 15 | "@emotion/styled": "^11.0.0", 16 | "@stripe/react-stripe-js": "^1.4.0", 17 | "@stripe/stripe-js": "^1.13.2", 18 | "framer-motion": "^4.0.3", 19 | "html-react-parser": "^1.2.6", 20 | "next": "latest", 21 | "next-images": "^1.7.0", 22 | "nprogress": "^0.2.0", 23 | "react": "^17.0.2", 24 | "react-dom": "^17.0.2", 25 | "react-hook-form": "^7.2.3", 26 | "react-icons": "^4.2.0", 27 | "react-id-swiper": "^4.0.0", 28 | "react-redux": "^7.2.3", 29 | "react-responsive": "^8.2.0", 30 | "react-scroll": "^1.8.2", 31 | "redux": "^4.0.5", 32 | "swiper": "^6.5.8", 33 | "swr": "^0.5.5", 34 | "uuid": "^8.3.2" 35 | }, 36 | "license": "MIT" 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Harsimran Singh Barki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/Shipping/Success.js: -------------------------------------------------------------------------------- 1 | import { Button } from "@chakra-ui/button"; 2 | import { ArrowLeftIcon, ChevronLeftIcon } from "@chakra-ui/icons"; 3 | import { Box, Divider, Grid, Heading, HStack, Text, VStack } from "@chakra-ui/layout"; 4 | import { Spinner } from "@chakra-ui/spinner"; 5 | import { chakra } from "@chakra-ui/system"; 6 | import Link from "next/link"; 7 | import React from "react"; 8 | 9 | function Success({order}) { 10 | 11 | if (!order) { 12 | return ( 13 | 14 | 15 | 16 | 17 | 18 | ) 19 | } 20 | return ( 21 | 22 | 23 | Thank you for your purchase 24 | 25 | Order Ref: {''} {order?.customer_reference} 26 | 27 | 28 | 29 | 30 | ); 31 | } 32 | 33 | export default Success; 34 | -------------------------------------------------------------------------------- /components/RelatedProducts.js: -------------------------------------------------------------------------------- 1 | import { Box, Flex, Heading, Text } from "@chakra-ui/layout"; 2 | import { motion } from "framer-motion"; 3 | import Product from "./Product/Product"; 4 | import { v4 as uuidv4 } from "uuid"; 5 | 6 | function RelatedProducts({ products }) { 7 | if (!products || products.length === 0) return null; 8 | 9 | return ( 10 | 21 | 22 | Similar Products 23 | 24 | {products.map((product) => ( 25 | 33 | ))} 34 | 35 | 36 | 37 | ); 38 | } 39 | 40 | export default RelatedProducts; 41 | -------------------------------------------------------------------------------- /components/VariantPicker.js: -------------------------------------------------------------------------------- 1 | import { Button, ButtonGroup } from "@chakra-ui/button"; 2 | import { Box, Text } from "@chakra-ui/layout"; 3 | import { Select } from "@chakra-ui/select"; 4 | import React from "react"; 5 | import { v4 as uuidv4 } from "uuid"; 6 | 7 | function VariantPicker({ variantGroups = [], defaultValues = {}, ...props }) { 8 | if (!variantGroups || variantGroups.length === 0) return null; 9 | 10 | return ( 11 | <> 12 | {variantGroups.map(({ options, ...group }) => ( 13 | 14 | 15 | Choose Size 16 | 17 | 18 | 34 | 35 | ))} 36 | 37 | ); 38 | } 39 | 40 | export default VariantPicker; 41 | -------------------------------------------------------------------------------- /components/SearchBar.js: -------------------------------------------------------------------------------- 1 | import { Box, Flex, Text } from "@chakra-ui/layout"; 2 | import { Select } from "@chakra-ui/select"; 3 | import React from "react"; 4 | 5 | export const SearchBar = ({ categories }) => { 6 | return ( 7 | 8 | 16 | 17 | 18 | Brand 19 | 20 | 25 | 26 | 27 | 28 | Price 29 | 30 | 35 | 36 | 37 | 38 | Filter 39 | 40 | 45 | 46 | 47 | 48 | ); 49 | }; 50 | -------------------------------------------------------------------------------- /styles/theme.js: -------------------------------------------------------------------------------- 1 | import { extendTheme } from "@chakra-ui/react"; 2 | import { createBreakpoints } from "@chakra-ui/theme-tools"; 3 | 4 | const fonts = { mono: `'Menlo', monospace` }; 5 | 6 | const breakpoints = createBreakpoints({ 7 | sm: "40em", 8 | md: "52em", 9 | lg: "64em", 10 | xl: "80em", 11 | }); 12 | 13 | import { mode } from "@chakra-ui/theme-tools"; 14 | const theme = extendTheme({ 15 | colors: { 16 | black: "#000000", 17 | }, 18 | fonts: { 19 | heading: "Playfair Display, serif", 20 | body: "Source Sans Pro, sans-serif", 21 | }, 22 | fontWeights: { 23 | light: 300, 24 | normal: 400, 25 | medium: 500, 26 | semiBold: 600, 27 | bold: 700, 28 | boldest: 800, 29 | }, 30 | breakpoints, 31 | icons: { 32 | logo: { 33 | path: ( 34 | 41 | 42 | 46 | 47 | ), 48 | viewBox: "0 0 3000 3163", 49 | }, 50 | }, 51 | styles: { 52 | global: (props) => ({ 53 | body: { 54 | color: mode("#01020A", "#FAFAFA")(props), 55 | bg: mode("white", "#272343")(props), 56 | }, 57 | }), 58 | }, 59 | }); 60 | 61 | export default theme; 62 | -------------------------------------------------------------------------------- /components/Hero.js: -------------------------------------------------------------------------------- 1 | import { Box, Flex, Heading, Text } from "@chakra-ui/layout"; 2 | import { chakra } from "@chakra-ui/system"; 3 | import React from "react"; 4 | import heroBg from 'public/hero.jpg' 5 | import { motion } from "framer-motion"; 6 | 7 | function Hero() { 8 | const MotionText = motion(Text) 9 | const MotionHeading = motion(Heading) 10 | return ( 11 | 14 | 15 | 24 | 25 | 33 | Rapid Store 34 | 35 | 44 | Hottest Shoes Collection With {""} 45 | 46 | Rapid 1 Day Delivery 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | ); 56 | } 57 | 58 | export default Hero; 59 | -------------------------------------------------------------------------------- /components/Shipping/OrderTotal.js: -------------------------------------------------------------------------------- 1 | import { useCartState } from "@/context/cart"; 2 | import { Flex, VStack } from "@chakra-ui/layout"; 3 | import { chakra } from "@chakra-ui/system"; 4 | import React from "react"; 5 | 6 | function OrderTotal() { 7 | const { line_items, subtotal, total_unique_items } = useCartState(); 8 | return ( 9 | 10 | {line_items?.map((product) => { 11 | return ( 12 | 19 | 20 | {product?.name} 21 | 22 | 23 | {product?.price.formatted} x{" "} 24 | 25 | {product?.quantity} 26 | 27 | 28 | 29 | ); 30 | })} 31 | 32 | 38 | 39 | Total Items: 40 | 41 | {total_unique_items} 42 | 43 | 49 | 50 | Total Amount: 51 | 52 | {subtotal?.formatted_with_symbol} 53 | 54 | 55 | ); 56 | } 57 | 58 | export default OrderTotal; 59 | -------------------------------------------------------------------------------- /components/NavBar.js: -------------------------------------------------------------------------------- 1 | import { useCartState } from "@/context/cart"; 2 | import { Box, Container, Flex, HStack } from "@chakra-ui/layout"; 3 | import { chakra } from "@chakra-ui/system"; 4 | import Link from "next/link"; 5 | import React from "react"; 6 | import { FiShoppingBag, FiShoppingCart } from "react-icons/fi"; 7 | 8 | function NavBar() { 9 | const { line_items, subtotal, total_unique_items } = useCartState(); 10 | return ( 11 | <> 12 | 20 | 21 | 22 | 23 | 24 | 25 | Rapid Store 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | {total_unique_items == 0 ? null : ( 34 | 45 | {total_unique_items} 46 | 47 | )} 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | ); 58 | } 59 | 60 | export default NavBar; 61 | -------------------------------------------------------------------------------- /components/Product/Products.js: -------------------------------------------------------------------------------- 1 | import { Box, Container, Flex, Grid, Heading } from "@chakra-ui/layout"; 2 | import { motion } from "framer-motion"; 3 | import React from "react"; 4 | import Product from "./Product"; 5 | import { v4 as uuidv4 } from "uuid"; 6 | 7 | function Products({ merchant, categories, products }) { 8 | 9 | const easing = [0.6, -0.05, 0.01, 0.99]; 10 | const container = { 11 | hidden: { y: -10 }, 12 | show: { 13 | y: 0, 14 | transition: { 15 | staggerChildren: 0.2, 16 | ease: easing, 17 | }, 18 | }, 19 | }; 20 | 21 | const listItem = { 22 | hidden: { opacity: 0, y: -10 }, 23 | show: { opacity: 1, y: 0 }, 24 | }; 25 | 26 | const MotionGrid = motion(Grid); 27 | return ( 28 | 29 | 30 | Top Sellers 31 | 42 | {products.map((product) => { 43 | return ( 44 | 45 | {" "} 54 | 55 | ); 56 | })} 57 | 58 | 59 | 60 | ); 61 | } 62 | 63 | export default Products; 64 | -------------------------------------------------------------------------------- /context/cart.js: -------------------------------------------------------------------------------- 1 | import { createContext, useReducer, useEffect, useContext } from "react"; 2 | import { useCycle } from "framer-motion"; 3 | import commerce from "@/lib/commerce"; 4 | 5 | const CartStateContext = createContext(); 6 | const CartDispatchContext = createContext(); 7 | 8 | const SET_CART = "SET_CART"; 9 | const RESET = "RESET"; 10 | 11 | const initialState = { 12 | total_items: 0, 13 | total_unique_items: 0, 14 | line_items: [], 15 | }; 16 | 17 | const reducer = (state, action) => { 18 | switch (action.type) { 19 | case SET_CART: 20 | return { ...state, ...action.payload }; 21 | case RESET: 22 | return initialState; 23 | default: 24 | throw new Error(`Unknown action: ${action.type}`); 25 | } 26 | }; 27 | 28 | export const CartProvider = ({ children }) => { 29 | const [open, toggle] = useCycle(false, true); 30 | const [state, dispatch] = useReducer(reducer, initialState); 31 | 32 | useEffect(() => { 33 | getCart(); 34 | }, []); 35 | 36 | const getCart = async () => { 37 | try { 38 | const cart = await commerce.cart.retrieve(); 39 | 40 | dispatch({ type: SET_CART, payload: cart }); 41 | } catch (err) { 42 | // noop 43 | } 44 | }; 45 | 46 | const setCart = async (payload) => dispatch({ type: SET_CART, payload }); 47 | 48 | const showCart = () => { 49 | toggle(); 50 | document.body.classList.add("overflow-hidden"); 51 | }; 52 | 53 | const closeCart = () => { 54 | toggle(); 55 | document.body.classList.remove("overflow-hidden"); 56 | }; 57 | 58 | const reset = async () => dispatch({ type: RESET }); 59 | 60 | return ( 61 | 64 | 65 | {children} 66 | 67 | 68 | ); 69 | }; 70 | 71 | export const useCartState = () => useContext(CartStateContext); 72 | export const useCartDispatch = () => useContext(CartDispatchContext); 73 | -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import { ChakraProvider, ColorModeProvider, CSSReset } from "@chakra-ui/react"; 2 | import theme from "@/styles/theme"; 3 | import NavBar from "@/components/NavBar"; 4 | 5 | import Head from "next/head"; 6 | import { css, Global } from "@emotion/react"; 7 | import { CartProvider } from "@/context/cart"; 8 | import NProgress from "nprogress"; 9 | import "nprogress/nprogress.css"; 10 | import { Router } from "next/router"; 11 | import { CheckoutProvider } from "@/context/checkout"; 12 | import { AnimatePresence } from "framer-motion"; 13 | import Footer from "@/components/Footer"; 14 | 15 | NProgress.configure({ 16 | showSpinner: true, 17 | trickleRate: 0.1, 18 | trickleSpeed: 300, 19 | }); 20 | 21 | Router.events.on("routeChangeStart", () => { 22 | NProgress.start(); 23 | }); 24 | 25 | Router.events.on("routeChangeComplete", () => { 26 | NProgress.done(); 27 | }); 28 | 29 | Router.events.on("routeChangeError", () => { 30 | NProgress.done(); 31 | }); 32 | 33 | const GlobalStyle = ({ children }) => { 34 | return ( 35 | <> 36 | 37 | 38 | Rapid Store 39 | 40 | 41 | 53 | {children} 54 | 55 | ); 56 | }; 57 | 58 | function App({ Component, pageProps }) { 59 | return ( 60 | 61 | 62 | 67 | 68 | 69 | 70 | 71 | 72 | 73 |