├── 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 |
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 |
--------------------------------------------------------------------------------
/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 |
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 |
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 |
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 | | Name |
54 | Email |
55 | Role |
56 |
57 |
58 |
59 | {users.map(item=>{
60 | return(
61 |
62 | | {item.name} |
63 | {item.email} |
64 | handleRole(item._id,item.role)}>{item.role} |
65 |
66 |
67 | )
68 | })}
69 |
70 |
71 |
72 |
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 |
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
--------------------------------------------------------------------------------