├── vercel.json ├── public ├── favicon.ico ├── style.css └── vercel.svg ├── helpers ├── baseUrl.js ├── initDB.js └── Authenticated.js ├── pages ├── _app.js ├── product.js ├── api │ ├── orders.js │ ├── product │ │ └── [pid].js │ ├── users.js │ ├── signup.js │ ├── login.js │ ├── products.js │ ├── cart.js │ └── payment.js ├── index.js ├── login.js ├── signup.js ├── account.js ├── create.js ├── product │ └── [id].js └── cart.js ├── .gitignore ├── models ├── Product.js ├── User.js ├── Order.js └── Cart.js ├── package.json ├── components ├── Layout.js ├── Navbar.js └── UserRoles.js └── README.md /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "alias":"mystore202144.vercel.app" 3 | } -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mukeshphulwani66/mystore2021-Ecommerce-nextjs/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /helpers/baseUrl.js: -------------------------------------------------------------------------------- 1 | const baseUrl = process.env.NODE_ENV === 'production' ? "https://mystore202144.vercel.app": "http://localhost:3000" 2 | export default baseUrl -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import Layout from '../components/Layout' 2 | 3 | function MyApp({ Component, pageProps }) { 4 | return ( 5 | 6 | 7 | 8 | ) 9 | } 10 | 11 | 12 | export default MyApp -------------------------------------------------------------------------------- /pages/product.js: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | 3 | const Product = ()=>{ 4 | return( 5 |
6 |

product page

7 | go to home 8 |
9 | ) 10 | } 11 | 12 | export default Product -------------------------------------------------------------------------------- /pages/api/orders.js: -------------------------------------------------------------------------------- 1 | import initDb from '../../helpers/initDB' 2 | import Order from '../../models/Order' 3 | import Authenticated from '../../helpers/Authenticated' 4 | 5 | initDb() 6 | 7 | 8 | 9 | export default Authenticated(async (req,res)=>{ 10 | const orders = await Order.find({user:req.userId}) 11 | .populate("products.product") 12 | res.status(200).json(orders) 13 | }) -------------------------------------------------------------------------------- /public/style.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | @media (min-width:600px){ 4 | .rootcard{ 5 | display: flex; 6 | flex-wrap: wrap; 7 | justify-content: center; 8 | } 9 | 10 | .pcard{ 11 | max-width: 200px; 12 | margin: 20px; 13 | } 14 | } 15 | 16 | 17 | .authcard{ 18 | margin: 10px auto !important; 19 | max-width: 500px !important; 20 | padding: 10px; 21 | } 22 | input:focus{ 23 | border-bottom: 1px solid #1565c0 !important; 24 | box-shadow: 0 1px 0 0 #1565c0 !important; 25 | } -------------------------------------------------------------------------------- /.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 | 21 | # debug 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | 26 | # local env files 27 | .env.local 28 | .env.development.local 29 | .env.test.local 30 | .env.production.local 31 | -------------------------------------------------------------------------------- /models/Product.js: -------------------------------------------------------------------------------- 1 | import mongoose, { models } from 'mongoose' 2 | 3 | const productsSchema = new mongoose.Schema({ 4 | name:{ 5 | type:String, 6 | required:true 7 | }, 8 | price:{ 9 | type:Number, 10 | required:true 11 | }, 12 | description:{ 13 | type:String, 14 | required:true 15 | }, 16 | mediaUrl:{ 17 | type:String, 18 | required:true 19 | } 20 | }) 21 | 22 | export default mongoose.models.product || mongoose.model('product',productsSchema) -------------------------------------------------------------------------------- /helpers/initDB.js: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose' 2 | 3 | function initDB(){ 4 | if(mongoose.connections[0].readyState){ 5 | console.log("alredy connected") 6 | return 7 | } 8 | mongoose.connect(process.env.MONGO_URI,{ 9 | useNewUrlParser:true, 10 | useUnifiedTopology:true 11 | }) 12 | mongoose.connection.on('connected',()=>{ 13 | console.log("connected to mongo") 14 | }) 15 | mongoose.connection.on('error',(err)=>{ 16 | console.log("error connecting",err) 17 | }) 18 | } 19 | 20 | 21 | export default initDB -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mystore", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start" 9 | }, 10 | "dependencies": { 11 | "bcryptjs": "^2.4.3", 12 | "js-cookie": "^2.2.1", 13 | "jsonwebtoken": "^8.5.1", 14 | "mongoose": "^5.9.23", 15 | "next": "9.4.4", 16 | "nookies": "^2.3.2", 17 | "react": "16.13.1", 18 | "react-dom": "16.13.1", 19 | "react-stripe-checkout": "^2.6.3", 20 | "stripe": "^8.76.0", 21 | "uuid": "^8.2.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /models/User.js: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose' 2 | 3 | const userSchema = new mongoose.Schema({ 4 | name:{ 5 | type:String, 6 | required:true 7 | }, 8 | email:{ 9 | type:String, 10 | required:true, 11 | unique:true 12 | } , 13 | password:{ 14 | type:String, 15 | required:true 16 | }, 17 | role:{ 18 | type:String, 19 | required:true, 20 | default:"user", 21 | enum:["user",'admin','root'] 22 | } 23 | },{ 24 | timestamps:true 25 | }) 26 | 27 | 28 | export default mongoose.models.User || mongoose.model('User',userSchema) -------------------------------------------------------------------------------- /helpers/Authenticated.js: -------------------------------------------------------------------------------- 1 | import jwt from 'jsonwebtoken' 2 | 3 | function Authenticated(icomponent){ 4 | return (req,res)=>{ 5 | const {authorization} = req.headers 6 | if(!authorization){ 7 | return res.status(401).json({error:"you must logged in"}) 8 | } 9 | try{ 10 | const {userId} = jwt.verify(authorization,process.env.JWT_SECRET) 11 | req.userId = userId 12 | return icomponent(req,res) 13 | }catch(err){ 14 | console.log(err) 15 | return res.status(401).json({error:"you must logged in"}) 16 | } 17 | 18 | } 19 | } 20 | 21 | 22 | export default Authenticated -------------------------------------------------------------------------------- /models/Order.js: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose' 2 | import { truncate } from 'fs'; 3 | const {ObjectId} = mongoose.Schema.Types 4 | 5 | const orderSchema = new mongoose.Schema({ 6 | user:{ 7 | type:ObjectId, 8 | ref:"User" 9 | }, 10 | products:[ 11 | { 12 | quantity:{type:Number,default:1}, 13 | product:{type:ObjectId,ref:"product"} 14 | } 15 | ], 16 | email:{ 17 | type:String, 18 | required:true 19 | }, 20 | total:{ 21 | type:Number, 22 | required:true 23 | } 24 | },{ 25 | timestamps:true 26 | }) 27 | 28 | 29 | export default mongoose.models.Order || mongoose.model("Order",orderSchema) -------------------------------------------------------------------------------- /components/Layout.js: -------------------------------------------------------------------------------- 1 | import NavBar from "./Navbar"; 2 | import Head from 'next/head' 3 | 4 | const layout=({children})=>{ 5 | return( 6 | <> 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {children} 15 | 16 | 17 | ) 18 | } 19 | 20 | 21 | export default layout -------------------------------------------------------------------------------- /models/Cart.js: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose' 2 | const {ObjectId} = mongoose.Schema.Types 3 | 4 | const cartSchema = new mongoose.Schema({ 5 | user:{ 6 | type:ObjectId, 7 | ref:"User" 8 | }, 9 | products:[ 10 | { 11 | quantity:{type:Number,default:1}, 12 | product:{type:ObjectId,ref:"product"} 13 | } 14 | ] 15 | }) 16 | 17 | 18 | export default mongoose.models.Cart || mongoose.model("Cart",cartSchema) 19 | 20 | 21 | 22 | // { 23 | // user:"214234214", 24 | // products:[{_id:"2213123",quantity:1,product:"324534"},{_id:"2313124",quantity:3,product:"5464654"},] 25 | // }, 26 | // { 27 | // user:"wrrwefwfw", 28 | // products:[{quantity:1,product:"3424"},{quantity:1,product:"32423"},] 29 | // }, -------------------------------------------------------------------------------- /pages/api/product/[pid].js: -------------------------------------------------------------------------------- 1 | import Product from '../../../models/Product' 2 | import initDB from '../../../helpers/initDB' 3 | 4 | initDB() 5 | 6 | export default async (req,res)=>{ 7 | switch(req.method){ 8 | case "GET": 9 | await getProduct(req,res) 10 | break; 11 | case "DELETE": 12 | await deleteProduct(req,res) 13 | break; 14 | } 15 | 16 | } 17 | 18 | 19 | const getProduct = async (req,res)=>{ 20 | const {pid } = req.query 21 | const product = await Product.findOne({_id:pid}) 22 | res.status(200).json(product) 23 | } 24 | 25 | const deleteProduct = async (req,res)=>{ 26 | const {pid } = req.query 27 | await Product.findByIdAndDelete({_id:pid}) 28 | res.status(200).json({}) 29 | } -------------------------------------------------------------------------------- /pages/api/users.js: -------------------------------------------------------------------------------- 1 | import User from '../../models/User' 2 | import Authenticated from '../../helpers/Authenticated' 3 | 4 | 5 | export default async (req,res)=>{ 6 | switch(req.method){ 7 | case "GET": 8 | await fetchUsers(req,res) 9 | break 10 | case "PUT": 11 | await ChangeRole(req,res) 12 | break 13 | 14 | } 15 | } 16 | 17 | 18 | const fetchUsers = Authenticated(async(req,res)=>{ 19 | const users = await User.find({_id :{$ne:req.userId}}).select("-password") 20 | res.status(200).json(users) 21 | }) 22 | 23 | const ChangeRole = Authenticated(async(req,res)=>{ 24 | const {_id,role} = req.body 25 | const newRole = role=="user"?"admin":"user" 26 | const users = await User.findOneAndUpdate( 27 | {_id}, 28 | {role:newRole}, 29 | {new:true} 30 | ).select("-password") 31 | res.status(200).json(users) 32 | }) -------------------------------------------------------------------------------- /pages/api/signup.js: -------------------------------------------------------------------------------- 1 | import initDB from '../../helpers/initDB' 2 | import User from '../../models/User' 3 | import bcrypt from 'bcryptjs' 4 | import Cart from '../../models/Cart' 5 | initDB() 6 | 7 | 8 | export default async (req,res)=>{ 9 | const {name,email,password} = req.body 10 | try{ 11 | if(!name || !email || !password){ 12 | return res.status(422).json({error:"please ass all the fields"}) 13 | } 14 | const user = await User.findOne({email}) 15 | if(user){ 16 | return res.status(422).json({error:"user already exists with that email"}) 17 | } 18 | const hashedPassword = await bcrypt.hash(password,12) 19 | const newUser = await new User({ 20 | name, 21 | email, 22 | password:hashedPassword 23 | }).save() 24 | await new Cart({user:newUser._id}).save() 25 | res.status(201).json({message:"signup success"}) 26 | }catch(err){ 27 | console.log(err) 28 | } 29 | } -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /pages/api/login.js: -------------------------------------------------------------------------------- 1 | import initDB from '../../helpers/initDB' 2 | import User from '../../models/User' 3 | import bcrypt from 'bcryptjs' 4 | import jwt from 'jsonwebtoken' 5 | 6 | initDB() 7 | 8 | export default async (req,res)=>{ 9 | const {email,password} = req.body 10 | try{ 11 | if(!email || !password){ 12 | return res.status(422).json({error:"please ass all the fields"}) 13 | } 14 | const user = await User.findOne({email}) 15 | if(!user){ 16 | return res.status(404).json({error:"user dont exists with that email"}) 17 | } 18 | const doMatch = await bcrypt.compare(password,user.password) 19 | if(doMatch){ 20 | const token = jwt.sign({userId:user._id},process.env.JWT_SECRET,{ 21 | expiresIn:"7d" 22 | }) 23 | const {name,role,email} = user 24 | res.status(201).json({token,user:{name,role,email}}) 25 | }else{ 26 | return res.status(401).json({error:"email or password dont match"}) 27 | } 28 | }catch(err){ 29 | console.log(err) 30 | } 31 | } -------------------------------------------------------------------------------- /pages/api/products.js: -------------------------------------------------------------------------------- 1 | import initDB from '../../helpers/initDB' 2 | import Product from '../../models/Product' 3 | 4 | initDB() 5 | 6 | export default async (req,res)=>{ 7 | switch (req.method) 8 | { 9 | case "GET": 10 | await getallProducts(req,res) 11 | break 12 | case "POST": 13 | await saveProduct(req,res) 14 | break 15 | } 16 | } 17 | 18 | 19 | const getallProducts = async (req,res)=>{ 20 | try{ 21 | const products = await Product.find() 22 | res.status(200).json(products) 23 | }catch(err){ 24 | console.log(err) 25 | } 26 | 27 | } 28 | 29 | 30 | const saveProduct = async (req,res)=>{ 31 | 32 | const {name,price,description,mediaUrl} = req.body 33 | try{ 34 | if(!name || !price || !description || !mediaUrl){ 35 | return res.status(422).json({error:"Please add all the fields"}) 36 | } 37 | const product = await new Product({ 38 | name, 39 | price, 40 | description, 41 | mediaUrl 42 | }).save() 43 | res.status(201).json(product) 44 | }catch(err){ 45 | res.status(500).json({error:"internal server error"}) 46 | console.log(err) 47 | } 48 | 49 | 50 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | ``` 12 | 13 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 14 | 15 | You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. 16 | 17 | ## Learn More 18 | 19 | To learn more about Next.js, take a look at the following resources: 20 | 21 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 22 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 23 | 24 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 25 | 26 | ## Deploy on Vercel 27 | 28 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/import?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 29 | 30 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 31 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import baseUrl from '../helpers/baseUrl' 3 | 4 | const Home = ({products})=>{ 5 | 6 | 7 | const productList = products.map(product=>{ 8 | return( 9 |
10 |
11 | 12 | {product.name} 13 |
14 |
15 |

₹ {product.price}

16 |
17 |
18 | View Product 19 |
20 |
21 | ) 22 | }) 23 | 24 | // console.log(products) 25 | return( 26 |
27 | {productList} 28 |
29 | ) 30 | } 31 | 32 | 33 | export async function getStaticProps(){ 34 | const res = await fetch(`${baseUrl}/api/products`) 35 | const data = await res.json() 36 | return { 37 | props:{ 38 | products:data 39 | } 40 | } 41 | } 42 | 43 | // export async function getServerSideProps(){ 44 | // const res = await fetch(`${baseUrl}/api/products`) 45 | // const data = await res.json() 46 | // return { 47 | // props:{ 48 | // products:data 49 | // } 50 | // } 51 | // } 52 | 53 | 54 | 55 | 56 | 57 | 58 | export default Home -------------------------------------------------------------------------------- /components/Navbar.js: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import {useRouter} from 'next/router' 3 | import {parseCookies} from 'nookies' 4 | import cookie from 'js-cookie' 5 | const NavBar = ()=>{ 6 | const router = useRouter() 7 | const cookieuser = parseCookies() 8 | const user = cookieuser.user ? JSON.parse(cookieuser.user) : "" 9 | 10 | function isActive(route){ 11 | if(route== router.pathname){ 12 | return "active" 13 | } 14 | else "" 15 | } 16 | 17 | return( 18 | 48 | ) 49 | } 50 | 51 | 52 | export default NavBar -------------------------------------------------------------------------------- /pages/login.js: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import {useState} from 'react' 3 | import baseUrl from '../helpers/baseUrl' 4 | import cookie from 'js-cookie' 5 | import {useRouter} from 'next/router' 6 | const Login = ()=>{ 7 | const [email,setEmail] = useState("") 8 | const [password,setPassword] = useState("") 9 | const router = useRouter() 10 | const userLogin = async (e)=>{ 11 | e.preventDefault() 12 | const res = await fetch(`${baseUrl}/api/login`,{ 13 | method:"POST", 14 | headers:{ 15 | "Content-Type":"application/json" 16 | }, 17 | body:JSON.stringify({ 18 | email, 19 | password 20 | }) 21 | }) 22 | 23 | const res2 = await res.json() 24 | if(res2.error){ 25 | M.toast({html: res2.error,classes:"red"}) 26 | }else{ 27 | console.log(res2) 28 | cookie.set('token',res2.token) 29 | cookie.set('user',res2.user) 30 | router.push('/account') 31 | } 32 | 33 | } 34 | return( 35 |
36 |

LOGIN

37 |
userLogin(e)}> 38 | setEmail(e.target.value)} 41 | /> 42 | setPassword(e.target.value)} 45 | /> 46 | 49 |
Dont have a account ?
50 |
51 | 52 |
53 | ) 54 | } 55 | 56 | export default Login -------------------------------------------------------------------------------- /pages/signup.js: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import {useState} from 'react' 3 | import baseUrl from '../helpers/baseUrl' 4 | import { useRouter } from 'next/router' 5 | const Signup = ()=>{ 6 | const [name,setName] = useState("") 7 | const [email,setEmail] = useState("") 8 | const [password,setPassword] = useState("") 9 | const router = useRouter() 10 | 11 | const userSignup = async(e)=>{ 12 | e.preventDefault() 13 | const res = await fetch(`${baseUrl}/api/signup`,{ 14 | method:"POST", 15 | headers:{ 16 | "Content-Type":"application/json" 17 | }, 18 | body:JSON.stringify({ 19 | name, 20 | email, 21 | password 22 | }) 23 | }) 24 | 25 | const res2 = await res.json() 26 | if(res2.error){ 27 | M.toast({html: res2.error,classes:"red"}) 28 | }else{ 29 | M.toast({html: res2.message,classes:"green"}) 30 | router.push('/login') 31 | } 32 | } 33 | return( 34 |
35 |

SignUP

36 |
userSignup(e)}> 37 | setName(e.target.value)} 40 | /> 41 | setEmail(e.target.value)} 44 | /> 45 | setPassword(e.target.value)} 48 | /> 49 | 52 |
Already have a account ?
53 |
54 | 55 |
56 | ) 57 | } 58 | 59 | export default Signup -------------------------------------------------------------------------------- /pages/api/cart.js: -------------------------------------------------------------------------------- 1 | import jwt from 'jsonwebtoken' 2 | import Cart from '../../models/Cart' 3 | import Authenticated from '../../helpers/Authenticated' 4 | import initDb from '../../helpers/initDB' 5 | 6 | 7 | initDb() 8 | 9 | 10 | export default async (req,res)=>{ 11 | switch(req.method){ 12 | case "GET": 13 | await fetchUserCart(req,res) 14 | break 15 | case "PUT": 16 | await addProduct(req,res) 17 | break 18 | case "DELETE": 19 | await removeProduct(req,res) 20 | break 21 | } 22 | } 23 | 24 | 25 | 26 | const fetchUserCart = Authenticated(async (req,res) =>{ 27 | const cart = await Cart.findOne({user:req.userId}) 28 | .populate("products.product") 29 | res.status(200).json(cart.products) 30 | }) 31 | 32 | 33 | const addProduct = Authenticated(async(req,res)=>{ 34 | const {quantity,productId} = req.body 35 | 36 | const cart = await Cart.findOne({user: req.userId}) 37 | const pExists = cart.products.some(pdoc => productId === pdoc.product.toString() ) 38 | 39 | if(pExists){ 40 | await Cart.findOneAndUpdate( 41 | {_id:cart._id,"products.product":productId}, 42 | {$inc:{"products.$.quantity":quantity}} 43 | ) 44 | }else{ 45 | const newProduct = {quantity,product:productId} 46 | await Cart.findOneAndUpdate( 47 | {_id:cart._id}, 48 | {$push:{products:newProduct}} 49 | ) 50 | } 51 | res.status(200).json({message:"product added to cart"}) 52 | 53 | 54 | }) 55 | 56 | 57 | const removeProduct = Authenticated(async (req,res)=>{ 58 | const {productId} = req.body 59 | const cart = await Cart.findOneAndUpdate( 60 | {user:req.userId}, 61 | {$pull:{products:{product:productId}}}, 62 | {new:true} 63 | ).populate("products.product") 64 | res.status(200).json(cart.products) 65 | }) -------------------------------------------------------------------------------- /components/UserRoles.js: -------------------------------------------------------------------------------- 1 | import {useState,useEffect} from 'react' 2 | import {parseCookies} from 'nookies' 3 | import baseUrl from '../helpers/baseUrl' 4 | 5 | function UserRoles(){ 6 | const [users,setUsers] = useState([]) 7 | const {token} = parseCookies() 8 | useEffect(()=>{ 9 | fetchUser() 10 | },[]) 11 | const fetchUser = async ()=>{ 12 | const res = await fetch(`${baseUrl}/api/users`,{ 13 | headers:{ 14 | "Authorization":token 15 | } 16 | }) 17 | const res2 = await res.json() 18 | console.log(res2) 19 | setUsers(res2) 20 | } 21 | 22 | const handleRole = async (_id,role)=>{ 23 | const res = await fetch(`${baseUrl}/api/users`,{ 24 | method:"PUT", 25 | headers:{ 26 | "Content-Type":"application/json", 27 | "Authorization":token 28 | }, 29 | body:JSON.stringify({ 30 | _id, 31 | role 32 | }) 33 | }) 34 | const res2 = await res.json() 35 | console.log(res2) 36 | // setUsers(res2) 37 | const updatedUsers = users.map(user=>{ 38 | if((user.role != res2.role) && (user.email == res2.email)){ 39 | return res2 40 | }else{ 41 | return user 42 | } 43 | }) 44 | setUsers(updatedUsers) 45 | } 46 | 47 | return( 48 | <> 49 |

User roles

50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | {users.map(item=>{ 60 | return( 61 | 62 | 63 | 64 | 65 | 66 | 67 | ) 68 | })} 69 | 70 | 71 | 72 |
NameEmailRole
{item.name}{item.email}handleRole(item._id,item.role)}>{item.role}
73 | 74 | 75 | ) 76 | } 77 | 78 | export default UserRoles -------------------------------------------------------------------------------- /pages/api/payment.js: -------------------------------------------------------------------------------- 1 | import Stripe from 'stripe' 2 | import {v4 as uuidV4 } from 'uuid' 3 | import Cart from '../../models/Cart' 4 | import jwt from 'jsonwebtoken' 5 | import Order from '../../models/Order' 6 | import initDb from '../../helpers/initDB' 7 | 8 | 9 | initDb() 10 | 11 | 12 | const stripe = Stripe(process.env.STRIPE_SECRET) 13 | export default async (req,res)=>{ 14 | const {paymentInfo} = req.body 15 | const {authorization} = req.headers 16 | if(!authorization){ 17 | return res.status(401).json({error:"you must logged in"}) 18 | } 19 | 20 | try{ 21 | const {userId} = jwt.verify(authorization,process.env.JWT_SECRET) 22 | const cart = await Cart.findOne({user:userId}).populate("products.product") 23 | let price = 0 24 | cart.products.forEach(item=>{ 25 | price = price + item.quantity * item.product.price 26 | }) 27 | const prevCustomer = await stripe.customers.list({ 28 | email:paymentInfo.email 29 | }) 30 | const isExistingCustomer = prevCustomer.data.length > 0 31 | let newCustomer 32 | if(!isExistingCustomer){ 33 | newCustomer = await stripe.customers.create({ 34 | email:paymentInfo.email, 35 | source:paymentInfo.id 36 | }) 37 | } 38 | 39 | await stripe.charges.create( 40 | { 41 | currency:"INR", 42 | amount: price * 100, 43 | receipt_email:paymentInfo.email, 44 | customer: isExistingCustomer ? prevCustomer.data[0].id : newCustomer.id, 45 | description:`you purchased a product | ${paymentInfo.email}` 46 | },{ 47 | idempotencyKey:uuidV4() 48 | } 49 | ) 50 | await new Order({ 51 | user:userId, 52 | email:paymentInfo.email, 53 | total:price, 54 | products:cart.products 55 | }).save() 56 | await Cart.findOneAndUpdate( 57 | {_id:cart._id}, 58 | {$set:{products:[]}} 59 | ) 60 | res.status(200).json({message:"payment was successful"}) 61 | 62 | 63 | 64 | 65 | 66 | 67 | }catch(err){ 68 | console.log(err) 69 | return res.status(401).json({error:"error processing payment"}) 70 | } 71 | 72 | 73 | } -------------------------------------------------------------------------------- /pages/account.js: -------------------------------------------------------------------------------- 1 | import {parseCookies} from 'nookies' 2 | import baseUrl from '../helpers/baseUrl' 3 | import {useEffect,useRef} from 'react' 4 | import UserRoles from '../components/UserRoles' 5 | const Account = ({orders})=>{ 6 | const orderCard = useRef(null) 7 | const cookie = parseCookies() 8 | const user = cookie.user ? JSON.parse(cookie.user): "" 9 | 10 | useEffect(()=>{ 11 | M.Collapsible.init(orderCard.current) 12 | },[]) 13 | const OrderHistory = ()=>{ 14 | return( 15 | 36 | 37 | ) 38 | } 39 | 40 | return( 41 |
42 |
43 |

{user.name}

44 |

{user.email}

45 |
46 |

Order History

47 | { 48 | orders.length == 0? 49 |
50 |
Your have no order History
51 |
52 | : 53 | } 54 | {user.role == "root" 55 | && 56 | } 57 |
58 | ) 59 | } 60 | 61 | 62 | export async function getServerSideProps(ctx){ 63 | const {token} = parseCookies(ctx) 64 | if(!token){ 65 | const {res} = ctx 66 | res.writeHead(302,{Location:"/login"}) 67 | res.end() 68 | } 69 | 70 | const res = await fetch(`${baseUrl}/api/orders`,{ 71 | headers:{ 72 | "Authorization":token 73 | } 74 | }) 75 | const res2 = await res.json() 76 | console.log(res2) 77 | 78 | return { 79 | props:{orders:res2} 80 | } 81 | } 82 | 83 | 84 | 85 | 86 | export default Account -------------------------------------------------------------------------------- /pages/create.js: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import {useState} from 'react' 3 | import baseUrl from '../helpers/baseUrl' 4 | import {parseCookies} from 'nookies' 5 | const Create = ()=>{ 6 | const [name,setName] = useState("") 7 | const [price,setPrice] = useState("") 8 | const [media,setMedia] = useState("") 9 | const [description,setDescription] = useState("") 10 | const handleSubmit = async (e)=>{ 11 | e.preventDefault() 12 | try{ 13 | const mediaUrl = await imageUpload() 14 | const res = await fetch(`${baseUrl}/api/products`,{ 15 | method:"POST", 16 | headers:{ 17 | 'Content-Type':'application/json' 18 | }, 19 | body:JSON.stringify({ 20 | name, 21 | price, 22 | mediaUrl, 23 | description 24 | }) 25 | }) 26 | const res2 = await res.json() 27 | if(res2.error){ 28 | M.toast({html: res2.error,classes:"red"}) 29 | }else{ 30 | M.toast({html: "Product saved",classes:"green"}) 31 | } 32 | }catch(err){ 33 | console.log(err) 34 | } 35 | 36 | } 37 | const imageUpload = async ()=>{ 38 | const data = new FormData() 39 | data.append('file',media) 40 | data.append('upload_preset',"mystore") 41 | data.append('cloud_name',"cnq") 42 | const res = await fetch(" https://api.cloudinary.com/v1_1/cnq/image/upload",{ 43 | method:"POST", 44 | body:data 45 | }) 46 | const res2 = await res.json() 47 | return res2.url 48 | } 49 | return( 50 |
handleSubmit(e)}> 51 | {setName(e.target.value)}} 54 | /> 55 | {setPrice(e.target.value)}} 58 | /> 59 |
60 |
61 | File 62 | setMedia(e.target.files[0])} 65 | /> 66 |
67 |
68 | 69 |
70 |
71 | 72 | 77 | 80 |
81 | ) 82 | } 83 | 84 | 85 | 86 | export async function getServerSideProps(ctx){ 87 | const cookie = parseCookies(ctx) 88 | const user = cookie.user ? JSON.parse(cookie.user) : "" 89 | if(user.role == 'user' || user.role == '' ){ 90 | const {res} = ctx 91 | res.writeHead(302,{Location:"/"}) 92 | res.end() 93 | } 94 | 95 | 96 | return { 97 | props:{} 98 | } 99 | } 100 | 101 | export default Create -------------------------------------------------------------------------------- /pages/product/[id].js: -------------------------------------------------------------------------------- 1 | import {useRouter} from 'next/router' 2 | import baseUrl from '../../helpers/baseUrl' 3 | import {useRef,useEffect,useState} from 'react' 4 | import {parseCookies} from 'nookies' 5 | import cookie2 from 'js-cookie' 6 | const Product = ({product})=>{ 7 | const [quantity,setQuantity] = useState(1) 8 | const router = useRouter() 9 | const modalRef = useRef(null) 10 | const cookie = parseCookies() 11 | const user = cookie.user ? JSON.parse(cookie.user) : "" 12 | useEffect(()=>{ 13 | M.Modal.init(modalRef.current) 14 | },[]) 15 | if(router.isFallback){ 16 | return( 17 |

loading...

18 | ) 19 | } 20 | 21 | const getModal = ()=>{ 22 | return( 23 |
24 |
25 |

{product.name}

26 |

Are you sure you want to delete this

27 |
28 |
29 | 32 | 37 |
38 |
39 | 40 | ) 41 | } 42 | 43 | const deleteProduct = async ()=>{ 44 | const res = await fetch(`${baseUrl}/api/product/${product._id}`,{ 45 | method:"DELETE" 46 | }) 47 | await res.json() 48 | router.push('/') 49 | } 50 | 51 | const AddToCart = async ()=>{ 52 | const res = await fetch(`${baseUrl}/api/cart`,{ 53 | method:"PUT", 54 | headers:{ 55 | "Content-Type":"application/json", 56 | "Authorization":cookie.token 57 | }, 58 | body:JSON.stringify({ 59 | quantity, 60 | productId:product._id 61 | }) 62 | }) 63 | const res2 = await res.json() 64 | if(res2.error){ 65 | M.toast({html:error,classes:"red"}) 66 | cookie2.remove("user") 67 | cookie2.remove("token") 68 | router.push('/login') 69 | } 70 | M.toast({html:res2.message,classes:"green"}) 71 | 72 | } 73 | 74 | return( 75 |
76 |

{product.name}

77 | 78 |
RS {product.price}
79 | setQuantity(Number(e.target.value))} 85 | placeholder="Qunatity" 86 | /> 87 | {user? 88 | 93 | : 94 | 100 | } 101 | 102 |

103 | {product.description} 104 |

105 | {user.role != 'user' 106 | && 107 | 110 | } 111 | 112 | 113 | {getModal()} 114 |
115 | ) 116 | } 117 | 118 | // export async function getServerSideProps({params:{id}}) { 119 | // const res = await fetch(`${baseUrl}/api/product/${id}`) 120 | // const data = await res.json() 121 | // return { 122 | // props: {product:data} 123 | // } 124 | // } 125 | export async function getStaticProps({params:{id}}) { 126 | const res = await fetch(`${baseUrl}/api/product/${id}`) 127 | const data = await res.json() 128 | return { 129 | props: {product:data} 130 | } 131 | } 132 | 133 | export async function getStaticPaths() { 134 | return { 135 | paths: [ 136 | { params: { id:"5f0f502b9cb9363990f3de6c" } } 137 | ], 138 | fallback: true 139 | } 140 | } 141 | 142 | export default Product -------------------------------------------------------------------------------- /pages/cart.js: -------------------------------------------------------------------------------- 1 | import baseUrl from '../helpers/baseUrl' 2 | import { parseCookies} from 'nookies' 3 | import cookie from 'js-cookie' 4 | import {useRouter} from 'next/router' 5 | import Link from 'next/link' 6 | import {useState} from 'react' 7 | 8 | import StripeCheckout from 'react-stripe-checkout'; 9 | 10 | const Cart = ({error,products})=>{ 11 | const {token} = parseCookies() 12 | const router = useRouter() 13 | const [cProducts,setCartProduct] = useState(products) 14 | let price = 0 15 | if(!token){ 16 | return( 17 |
18 |

please login to view your cart

19 | 20 |
21 | ) 22 | } 23 | if(error){ 24 | M.toast({html:error,classes:"red"}) 25 | cookie.remove("user") 26 | cookie.remove("token") 27 | router.push('/login') 28 | 29 | } 30 | const handleRemove = async (pid)=>{ 31 | const res = await fetch(`${baseUrl}/api/cart`,{ 32 | method:"DELETE", 33 | headers:{ 34 | "Content-Type":"application/json", 35 | "Authorization":token 36 | }, 37 | body:JSON.stringify({ 38 | productId:pid 39 | }) 40 | }) 41 | 42 | const res2 = await res.json() 43 | setCartProduct(res2) 44 | } 45 | const CartItems = ()=>{ 46 | return( 47 | <> 48 | {cProducts.map(item=>{ 49 | price = price + item.quantity * item.product.price 50 | return( 51 |
52 | 53 |
54 |
{item.product.name}
55 |
{item.quantity} x ₹ {item.product.price}
56 | 57 |
58 |
59 | ) 60 | })} 61 | 62 | ) 63 | } 64 | 65 | const handleCheckout = async (paymentInfo)=>{ 66 | console.log(paymentInfo) 67 | const res = await fetch(`${baseUrl}/api/payment`,{ 68 | method:"POST", 69 | headers:{ 70 | "Content-Type":"application/json", 71 | "Authorization":token 72 | }, 73 | body:JSON.stringify({ 74 | paymentInfo 75 | }) 76 | }) 77 | const res2 = await res.json() 78 | M.toast({html: res2.mesage,classes:"green "}) 79 | router.push('/') 80 | } 81 | 82 | const TotalPrice = ()=>{ 83 | return( 84 |
85 |
total ₹ {price}
86 | {products.length != 0 87 | && 0 ? products[0].product.mediaUrl:""} 91 | currency="INR" 92 | shippingAddress={true} 93 | billingAddress={true} 94 | zipCode={true} 95 | stripeKey="pk_test_51H6fgDEta3rHzkPYGgIOQZSFrukEzAl71AOnyAUjyGR8uJPDaGfALQYWre4F5g0Quyh9d7PTphh56SmUlhtsQYmd00DZwB9gMj" 96 | token={(paymentInfo)=>handleCheckout(paymentInfo)} 97 | > 98 | 99 | 100 | } 101 | 102 |
103 | ) 104 | } 105 | return( 106 |
107 | 108 | 109 |
110 | 111 | ) 112 | } 113 | 114 | 115 | export async function getServerSideProps(ctx){ 116 | const {token} = parseCookies(ctx) 117 | if(!token){ 118 | return { 119 | props:{products:[]} 120 | } 121 | } 122 | const res = await fetch(`${baseUrl}/api/cart`,{ 123 | headers:{ 124 | "Authorization":token 125 | } 126 | }) 127 | const products = await res.json() 128 | if(products.error){ 129 | return{ 130 | props:{error:products.error} 131 | } 132 | } 133 | console.log("products",products) 134 | return { 135 | props:{products} 136 | } 137 | } 138 | 139 | 140 | 141 | export default Cart --------------------------------------------------------------------------------