Skip to content

Instantly share code, notes, and snippets.

@shivam-jha2712
Forked from adrianhajdin/StateContext.js
Created September 10, 2022 21:05
Show Gist options
  • Save shivam-jha2712/1d73ef599b8585494bf10e29d8095d04 to your computer and use it in GitHub Desktop.
Save shivam-jha2712/1d73ef599b8585494bf10e29d8095d04 to your computer and use it in GitHub Desktop.
Build and Deploy a Modern Full Stack ECommerce Application with Stripe
export default {
name: 'banner',
title: 'Banner',
type: 'document',
fields: [
{
name: 'image',
title: 'Image',
type: 'image',
options: {
hotspot: true,
},
},
{
name: 'buttonText',
title: 'ButtonText',
type: 'string',
},
{
name: 'product',
title: 'Product',
type: 'string',
},
{
name: 'desc',
title: 'Desc',
type: 'string',
},
{
name: 'smallText',
title: 'SmallText',
type: 'string',
},
{
name: 'midText',
title: 'MidText',
type: 'string',
},
{
name: 'largeText1',
title: 'LargeText1',
type: 'string',
},
{
name: 'largeText2',
title: 'LargeText2',
type: 'string',
},
{
name: 'discount',
title: 'Discount',
type: 'string',
},
{
name: 'saleTime',
title: 'SaleTime',
type: 'string',
},
],
};
html,
body, * {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
box-sizing: border-box;
}
::-webkit-scrollbar {
width: 0px;
}
a {
color: inherit;
text-decoration: none;
}
.main-container{
max-width: 1400px;
margin: auto;
width: 100%;
}
.layout{
padding: 10px;
}
.navbar-container{
display: flex;
justify-content: space-between;
margin: 6px 18px;
position: relative;
}
.marquee-text{
font-size: 29px;
font-weight: 600;
margin: 60px 0px;
color: #f02d34;
}
.marquee {
position: relative;
height: 400px;
width: 100%;
overflow-x: hidden;
}
.track {
position: absolute;
white-space: nowrap;
will-change: transform;
animation: marquee 15s linear infinite;
width: 180%;
}
.track:hover {
animation-play-state: paused;
}
@keyframes marquee {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
span.text-red {
-webkit-text-stroke: 1px #f02d34;
margin-left: 6px;
}
.logo{
color: gray;
font-size: 18px;
}
.cart-icon{
font-size: 25px;
color: gray;
cursor: pointer;
position: relative;
transition: transform .4s ease;
border: none;
background-color: transparent;
}
.cart-icon:hover{
transform: scale(1.1,1.1);
}
.cart-item-qty{
position: absolute;
right: -8px;
font-size: 12px;
color: #eee;
background-color: #f02d34;
width: 18px;
height: 18px;
border-radius: 50%;
text-align: center;
font-weight: 600;
}
.products-container{
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 15px;
margin-top: 20px;
width: 100%;
}
.product-card{
cursor: pointer;
transform: scale(1, 1);
transition: transform 0.5s ease;
color: #324d67;
}
.product-card:hover{
transform: scale(1.1,1.1)
}
.product-image{
border-radius: 15px;
background-color: #ebebeb;
transform: scale(1, 1);
transition: transform 0.5s ease;
}
.product-name{
font-weight: 500;
}
.product-price{
font-weight: 800;
margin-top: 6px;
color: black;
}
.hero-banner-container{
padding: 100px 40px;
background-color: #dcdcdc;
border-radius: 15px;
position: relative;
height: 500px;
line-height: 0.9;
width: 100%;
}
.hero-banner-container .beats-solo{
font-size: 20px;
}
.hero-banner-container button{
border-radius: 15px;
padding: 10px 16px;
background-color: #f02d34;
color: white;
border: none;
margin-top: 40px;
font-size: 18px;
font-weight: 500;
cursor: pointer;
z-index:10000 !important;
}
.hero-banner-container h3{
font-size: 4rem;
margin-top: 4px;
}
.hero-banner-container h1{
color: white;
font-size: 10em;
margin-left: -20px;
text-transform: uppercase;
}
.hero-banner-image{
position: absolute;
top: 0%;
right:20%;
width: 450px;
height: 450px;
}
.desc{
position: absolute;
right: 10%;
bottom: 5%;
width: 300px;
line-height: 1.3;
display: flex;
flex-direction: column;
color: #324d67;
}
.desc p{
color: #5f5f5f;
font-weight: 100;
text-align: end;
}
.desc h5{
margin-bottom: 12px;
font-weight: 700;
font-size: 16px;
/* color: black; */
align-self: flex-end;
}
.products-heading{
text-align: center;
margin: 40px 0px;
color: #324d67;
}
.products-heading h2{
font-size: 40px;
font-weight: 800;
}
.products-heading p{
font-size: 16px;
font-weight: 200;
}
.footer-banner-container{
padding: 100px 40px;
background-color: #f02d34;
border-radius: 15px;
position: relative;
height: 400px;
line-height: 1;
color: white;
width: 100%;
margin-top: 120px;
}
.banner-desc{
display: flex ;
justify-content: space-between;
}
.banner-desc button{
border-radius: 15px;
padding: 10px 16px;
background-color: white;
color: red;
border: none;
margin-top: 40px;
font-size: 18px;
font-weight: 500;
cursor: pointer;
}
.banner-desc .left h3{
font-weight: 900;
font-size: 80px;
margin-left: 25px;
}
.banner-desc .left p{
margin:18px;
}
.footer-banner-image{
position: absolute;
/* top: -35%;
left: 8%; */
top: -25%;
left: 25%;
}
.banner-desc .right{
line-height: 1.4;
}
.banner-desc .right h3{
font-weight: 800;
font-size: 60px;
}
.banner-desc .right p{
font-size: 18px;
}
.banner-desc .right .company-desc{
font-size: 14px;
font-weight: 300;
}
.cart-wrapper{
width: 100vw;
background: rgba(0, 0, 0, 0.5);
position: fixed;
right: 0;
top: 0;
z-index: 100;
/* will-change: transform; */
transition: all 1s ease-in-out;
}
.cart-container{
height: 100vh;
width: 600px;
background-color: white;
float: right;
padding: 40px 10px;
position: relative;
}
.footer-container{
color: #324d67;
text-align: center;
margin-top: 20px;
padding: 30px 10px;
font-weight: 700;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
justify-content: center;
}
.footer-container .icons{
font-size: 30px;
display: flex;
gap: 10px;
}
.cart-heading{
display: flex;
align-items: center;
font-size: 18px;
font-weight: 500;
cursor: pointer;
gap: 2px;
margin-left: 10px;
border: none;
background-color: transparent;
}
.cart-heading .heading{
margin-left: 10px;
}
.cart-num-items{
margin-left: 10px;
color: #f02d34;
}
.empty-cart{
margin:40px;
text-align:center;
}
.empty-cart h3{
font-weight: 600;
font-size: 20px;
}
.cancel{
cursor: pointer;
}
.product-container{
margin-top: 15px;
overflow: auto;
max-height: 70vh;
padding: 20px 10px;
}
.product{
display: flex;
gap: 30px;
padding: 20px;
}
.product .cart-product-image{
width:180px ;
height: 150px;
border-radius: 15px;
background-color: #ebebeb;
}
.item-desc .flex{
display: flex;
justify-content: space-between;
width: 350px;
color: #324d67;
}
.item-desc .bottom{
margin-top: 60px;
}
.flex h5{
font-size: 24px;
}
.flex h4{
font-size: 20px;
}
.total{
display: flex;
justify-content: space-between;
}
.total h3{
font-size: 22px;
}
.remove-item{
font-size: 24px;
color: #f02d34;
cursor: pointer;
background: transparent;
border: none;
}
.cart-bottom{
position: absolute;
bottom: 12px;
right: 5px;
width: 100%;
padding: 30px 65px;
}
.btn-container{
width: 400px;
margin: auto;
}
.btn{
width: 100%;
max-width: 400px;
padding: 10px 12px;
border-radius: 15px;
border: none;
font-size: 20px;
margin-top: 10px;
margin-top: 40px;
text-transform: uppercase;
background-color: #f02d34;
color: #fff;
cursor: pointer;
transform: scale(1, 1);
transition: transform 0.5s ease;
}
.btn:hover{
transform: scale(1.1,1.1);
}
.product-detail-container{
display: flex;
gap: 40px;
margin: 40px;
margin-top: 60px;
color: #324d67;
}
.product-detail-image{
border-radius: 15px;
background-color: #ebebeb;
width: 400px;
height: 400px;
cursor: pointer;
transition: .3s ease-in-out;
}
.product-detail-image:hover{
background-color: #f02d34;
}
.small-images-container{
display: flex;
gap: 10px;
margin-top: 20px;
}
.small-image{
border-radius: 8px;
background-color: #ebebeb;
width: 70px;
height: 70px;
cursor: pointer;
}
.selected-image{
background-color:#f02d34;
}
.reviews{
color: #f02d34;
margin-top: 10px;
display: flex;
gap: 5px;
align-items: center;
}
.product-detail-desc h4{
margin-top: 10px;
}
.product-detail-desc p{
margin-top: 10px;
}
.reviews p{
color: #324d67;
margin-top: 0px;
}
.product-detail-desc .price{
font-weight: 700 ;
font-size: 26px;
margin-top: 30px;
color:#f02d34;
}
.price .old-price, .product-price .old-price, .price .old-price{
color: gray;
text-decoration: line-through;
}
.product-detail-desc .quantity{
display: flex;
gap: 20px;
margin-top: 10px ;
align-items: center;
}
.product-detail-desc .buttons{
display: flex;
gap: 30px;
}
.buttons .add-to-cart{
padding: 10px 20px;
border: 1px solid #f02d34 ;
margin-top: 40px;
font-size: 18px;
font-weight: 500;
background-color: white;
color: #f02d34;
cursor: pointer;
width: 200px;
transform: scale(1, 1);
transition: transform 0.5s ease;
}
.buttons .add-to-cart:hover{
transform:scale(1.1,1.1)
}
.buttons .buy-now{
width: 200px;
padding: 10px 20px;
background-color: #f02d34;
color: white;
border: none;
margin-top: 40px;
font-size: 18px;
font-weight: 500;
cursor: pointer;
transform: scale(1, 1);
transition: transform 0.5s ease;
}
.buttons .buy-now:hover{
transform:scale(1.1,1.1)
}
.quantity-desc{
border: 1px solid gray;
padding: 6px;
}
.quantity-desc span{
font-size: 16px;
padding: 6px 12px;
cursor: pointer;
}
.quantity-desc .minus{
border-right: 1px solid gray;
color: #f02d34;
}
.quantity-desc .num{
border-right: 1px solid gray;
font-size: 20px;
}
.quantity-desc .plus{
color: rgb(49, 168, 49);
}
.maylike-products-wrapper{
margin-top: 120px;
}
.maylike-products-wrapper h2{
text-align: center;
margin: 50px;
color: #324d67;
font-size: 28px;
}
.maylike-products-container{
display: flex;
justify-content: center;
gap: 15px;
margin-top: 20px;
}
.max-qty{
font-weight: 500;
color: #f02d34;
}
.success-wrapper, .cancel-wrapper{
background-color: white;
min-height: 60vh;
}
.success, .cancel{
width: 1000px;
margin: auto;
margin-top: 160px;
background-color: #dcdcdc;
padding: 50px;
border-radius: 15px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.success .icon {
color: green;
font-size: 40px;
}
.success h2{
text-transform: capitalize;
margin-top: 15px 0px;
font-weight: 900;
font-size: 40px;
color:#324d67;
}
.success .email-msg{
font-size: 16px;
font-weight: 600;
text-align: center;
}
.cancel p{
font-size: 20px;
font-weight: 600;
}
.success .description{
font-size: 16px;
font-weight: 600;
text-align: center;
margin: 10px;
margin-top: 30px;
}
.success .description .email{
margin-left: 5px;
color: #f02d34;
}
.product-max-qty{
margin-top: 10px;
}
@media screen and (max-width:800px) {
.hero-banner-container{
height: 560px;
}
.hero-banner-image{
width: 77%;
height: 62%;
top: -2%;
right: -6%;
}
.footer-banner-container{
height: 560px;
margin-top: 80px;
}
.footer-banner-image{
width: 77%;
left: 30%;
top: 6%;
height: 56%
}
.banner-desc .left h3{
font-weight: 900;
font-size: 50px;
margin-left: 5px;
}
.banner-desc .left p{
margin:18px;
}
.banner-desc .right h3{
font-size: 45px;
}
.banner-desc .right p{
font-size: 18px;
}
.banner-desc .right .company-desc{
font-size: 14px;
}
.banner-desc{
flex-wrap: wrap;
gap: 20px;
}
.hero-banner-container{
line-height: 1.3;
}
.hero-banner-container h1{
font-size: 50px;
}
.hero-banner-container h3{
font-size: 40px;
}
.hero-banner-container button{
margin-top: 90px;
z-index: 10000;
}
.desc{
bottom: 60px;
}
.product-detail-container{
flex-wrap: wrap;
}
.product-detail-container .product-detail-image{
width: 350px;
height: 350px;
}
.cart-container{
width: 415px;
padding: 4px;
}
.cart-heading{
margin-top: 35px;
}
.product-container{
margin-top: 10px;
}
.product{
padding: 20px 5px;
}
.product .cart-product-image{
width: 25%;
height: 25%;
}
.buttons .add-to-cart{
width: 150px;
}
.buttons .buy-now{
width: 150px;
}
.product-detail-container{
margin: 20px;
}
.item-desc .flex{
width: 200px;
}
.top{
flex-wrap: wrap;
gap: 10px;
}
.item-desc .bottom{
margin-top: 30px;
}
.flex h5{
font-size: 16px;
color: #324d67;
}
.flex h4{
font-size: 16px;
color: black;
}
.cart-bottom{
padding: 30px;
}
.total h3{
font-size: 20px;
}
.track {
animation: marquee 10s linear infinite;
width: 550%;
}
.success-wrapper, .cancel-wrapper{
min-height: 69vh;
}
.success, .cancel {
width: 370px;
margin-top: 100px;
padding: 20px;
}
.success{
height: 350px;
}
.success h2{
font-size: 17px;
}
.btn-container{
width: 300px;
margin: auto;
}
}
{
"name": "sanity-ecommerce",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@sanity/client": "^3.2.0",
"@sanity/image-url": "^1.0.1",
"@stripe/stripe-js": "^1.25.0",
"canvas-confetti": "^1.5.1",
"next": "12.1.0",
"next-sanity-image": "^3.2.1",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-hot-toast": "^2.2.0",
"react-icons": "^4.3.1",
"stripe": "^8.209.0"
},
"devDependencies": {
"eslint": "^8.10.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-next": "^12.1.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-react": "^7.29.3",
"eslint-plugin-react-hooks": "^4.3.0"
}
}
import React, { createContext, useContext, useState, useEffect } from 'react';
import { toast } from 'react-hot-toast';
const Context = createContext();
export const StateContext = ({ children }) => {
const getLocalStorage = (name) => {
if (typeof window !== 'undefined') {
const storage = localStorage.getItem(name);
if (storage) return JSON.parse(localStorage.getItem(name));
if (name === 'cartItems') return [];
return 0;
}
};
const [showCart, setShowCart] = useState(false);
const [cartItems, setCartItems] = useState(getLocalStorage('cartItems'));
const [totalPrice, setTotalPrice] = useState(getLocalStorage('totalPrice'));
const [totalQuantities, setTotalQuantities] = useState(getLocalStorage('totalQuantities'));
const [qty, setQty] = useState(1);
let findProduct;
let index;
useEffect(() => {
localStorage.setItem('cartItems', JSON.stringify(cartItems));
localStorage.setItem('totalPrice', JSON.stringify(totalPrice));
localStorage.setItem('totalQuantities', JSON.stringify(totalQuantities));
}, [cartItems, totalPrice, totalQuantities]);
const onAdd = (product, quantity) => {
const checkProductInCart = cartItems.find(
(cartProduct) => cartProduct._id === product._id,
);
if (checkProductInCart) {
setTotalPrice(totalPrice + product.price * quantity);
setTotalQuantities(totalQuantities + quantity);
const updatedCartItems = cartItems.map((cartProduct) => {
if (cartProduct._id === product._id) {
return { ...cartProduct, quantity: cartProduct.quantity + quantity };
}
return cartProduct;
});
setCartItems(updatedCartItems);
toast.success(`${qty} ${product.name} added`);
} else {
setTotalPrice(totalPrice + product.price * quantity);
setTotalQuantities(totalQuantities + quantity);
// eslint-disable-next-line no-param-reassign
product.quantity = quantity;
setCartItems([...cartItems, { ...product }]);
toast.success(`${qty} ${product.name} added`);
}
};
const onRemove = (product) => {
findProduct = cartItems.find((item) => item._id === product._id);
const tempCart = cartItems.filter((item) => item._id !== product._id);
setTotalPrice(totalPrice - findProduct.price * findProduct.quantity);
setTotalQuantities(totalQuantities - findProduct.quantity);
setCartItems(tempCart);
};
const toggleCartItemQuantity = (id, value) => {
findProduct = cartItems.find((item) => item._id === id);
index = cartItems.findIndex((product) => product._id === id);
if (value === 'inc') {
findProduct.quantity += 1;
cartItems[index] = findProduct;
setTotalPrice(totalPrice + findProduct.price);
setTotalQuantities(totalQuantities + 1);
}
if (value === 'dec') {
if (findProduct.quantity > 1) {
findProduct.quantity -= 1;
cartItems[index] = findProduct;
setTotalPrice(totalPrice - findProduct.price);
setTotalQuantities(totalQuantities - 1);
}
}
};
const incQty = () => {
setQty((oldQty) => {
const tempQty = oldQty + 1;
return tempQty;
});
};
const decQty = () => {
setQty((oldQty) => {
let tempQty = oldQty - 1;
if (tempQty < 1) {
tempQty = 1;
}
return tempQty;
});
};
return (
<Context.Provider
// eslint-disable-next-line react/jsx-no-constructed-context-values
value={{
onAdd,
onRemove,
cartItems,
totalPrice,
totalQuantities,
setShowCart,
setCartItems,
setTotalPrice,
setTotalQuantities,
showCart,
incQty,
decQty,
qty,
toggleCartItemQuantity,
}}
>
{children}
</Context.Provider>
);
};
export const useStateContext = () => useContext(Context);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment