├── .gitignore ├── public ├── LLC.jpg └── script.js ├── routes ├── about.js ├── checkout.js ├── carts.js ├── products.js └── users.js ├── models ├── carts.js ├── users.js └── products.js ├── README.md ├── package.json ├── views ├── return.pug └── about.pug ├── .github └── workflows │ └── npm-publish.yml └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /public/LLC.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WENDYWEN20/CapstoneMongoDB/HEAD/public/LLC.jpg -------------------------------------------------------------------------------- /routes/about.js: -------------------------------------------------------------------------------- 1 | 2 | import {Router} from 'express' 3 | 4 | const router=new Router 5 | 6 | router.post('/', (req,res)=>{ 7 | console.log(req.params) 8 | res.render('about.pug') 9 | 10 | }) 11 | 12 | 13 | 14 | export default router -------------------------------------------------------------------------------- /models/carts.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | const cartsSchema = new mongoose.Schema({ 4 | name: { type: String, required: true}, 5 | images: { type: String }, 6 | price: { 7 | type: Number, 8 | required: true, 9 | }, 10 | 11 | }); 12 | 13 | const cartsModel = mongoose.model("carts", cartsSchema); 14 | 15 | export default cartsModel; 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Technologies used 4 | 5 | 1.Express\ 6 | 2.Mongoose\ 7 | 3.dotenv \ 8 | 4. use MongoDB as the database, pictures and item posted from backend \ 9 | 5. add Stripe for payment (under going) \ 10 | 6. Youtube Tutorial followed: https://www.youtube.com/watch?v=1r-F3FIONl8 \ 11 | 7. Youtube Tutorial followed: https://www.youtube.com/watch?v=4YjsG8u2QFA \ 12 | 8.Next Step: add Shopify Hydrogen Link@https://hydrogen.shopify.dev/ 13 | -------------------------------------------------------------------------------- /models/users.js: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose' 2 | 3 | const usersSchema= new mongoose.Schema({ 4 | username:{ type: String, 5 | required: true, 6 | minLength: 3, 7 | maxLength: 50, 8 | }, 9 | email:{ type: String, 10 | required: true, 11 | minLength: 8, 12 | maxLength: 1200, 13 | }, 14 | 15 | address:{ 16 | type: String, 17 | }, 18 | orderHistory:[] 19 | }) 20 | 21 | const usersModel=mongoose.model('users', usersSchema) 22 | 23 | export default usersModel -------------------------------------------------------------------------------- /public/script.js: -------------------------------------------------------------------------------- 1 | const button=document.querySelector('button') 2 | button.addEventListener('click', ()=>{ 3 | fetch('http:localhost:3000/create-checkout-session',{ 4 | method: 'POST', 5 | headers:{ 6 | 'Content-Type': 'application/json' 7 | }, 8 | body:JSON.stringify({}) 9 | }).then(res=>{ 10 | if (res.ok) return res.json() 11 | return res.json().then(json=>Promise.reject(json)) 12 | }).then(({url})=>{ 13 | window.location=url 14 | }).catch(e=>{console.error(e.error)}) 15 | }) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mongodb", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "type": "module", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "description": "", 13 | "dependencies": { 14 | "body-parser": "^1.20.3", 15 | "cors": "^2.8.5", 16 | "dotenv": "^16.4.5", 17 | "express": "^4.21.1", 18 | "mongoose": "^8.7.2", 19 | "morgan": "^1.10.0", 20 | "pug": "^3.0.3", 21 | "stripe": "^17.3.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /views/return.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | h1 Returning an item 5 | 6 | p="You can return an item for free within 30 days after receiving your order. It's also possible to return something to one of our stores if your order didn't have a delivery fee." 7 | p="Eligible online orders from October 24th, 2024 until January 23th, 2025 can be returned or exchanged within 60 days of receipt with our holiday extended return period." 8 | hr 9 | img(src='LLC.jpg') 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /models/products.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | const productsSchema = new mongoose.Schema({ 4 | name: { type: String, required: true, minLength: 3, maxLength: 50 }, 5 | description: { type: String, minLength: 12, maxLength: 1200 }, 6 | images: { type: String }, 7 | size: { 8 | type: String, 9 | Enum: ["S", "M", "L", "NA"], 10 | }, 11 | price: { 12 | type: Number, 13 | required: true, 14 | minLength: 1, 15 | maxLength: 10, 16 | }, 17 | gender: { 18 | type: String, 19 | Enum: ["man", "woman", "children"], 20 | }, 21 | }); 22 | 23 | const productsModel = mongoose.model("products", productsSchema); 24 | 25 | export default productsModel; 26 | -------------------------------------------------------------------------------- /routes/checkout.js: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import {Stripe} from "stripe" 3 | 4 | 5 | const router=new Router() 6 | router.post('/create-checkout-session', async(req,res)=>{ 7 | const stripe = new Stripe(process.env.STRIPE_PRIVATE_KEY); 8 | console.log(process.env.STRIPE_PRIVATE_KEY) 9 | try{const session =await stripe.checkout.sessions.create({ 10 | payment_method_types:['card'], 11 | mode: 'payment', 12 | line_items:[{price: 50, 13 | // '{{PRICE_ID}}', 14 | quantity: 1,}], 15 | // success_url: 'http://localhost:3000/success.html', 16 | // cancel_url: 'http://localhost:3000/cancel.html ' 17 | success_url: '${process.env.SERVER_URL}/success.html', 18 | cancel_url: '${process.env.SERVER_URL}/cancel.html ', 19 | 20 | }) 21 | 22 | }catch(e){res.status(500).json({error:e.message})} 23 | res.json({url: session.url}) 24 | console.log(session) 25 | }) 26 | export default router -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages 3 | 4 | name: Node.js Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: actions/setup-node@v4 16 | with: 17 | node-version: 20 18 | - run: npm ci 19 | - run: npm test 20 | 21 | publish-npm: 22 | needs: build 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v4 26 | - uses: actions/setup-node@v4 27 | with: 28 | node-version: 20 29 | registry-url: https://registry.npmjs.org/ 30 | - run: npm ci 31 | - run: npm publish 32 | env: 33 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 34 | -------------------------------------------------------------------------------- /views/about.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title='Company' 5 | link(rel="stylesheet", href="style.css") 6 | script(src='/myscript.js') 7 | body 8 | 9 | h1 CapStone Fullstack using Pug 10 | h2 Contact US 11 | 12 | p Everything we do is rooted in sport. Sport plays an increasingly important role in more and more people’s lives, on and off the field of play. It is central to every culture and society, and is core to our health and happiness. 13 | form(action='/create', method='post') 14 | a(href='/download') Download Our Catalog 15 | input(type='text') 16 | 17 | 18 | form(role='form' method='POST') 19 | div.form-group 20 | label(for='name') Name: 21 | input#name.form-control(type='text', placeholder='name' name='name') 22 | div.form-group 23 | label(for='email') Email: 24 | input#email.form-control(type='email', placeholder='name@email.com' name='email') 25 | button.btn.btn-primary(type="submit", name="asdf") Contact Customer Service 26 | h3 ADIDAS AG World of Sports 27 | h3 Adi-Dassler-Straße 1 28 | h3 91074 Herzogenaurach 29 | h3 Germany 30 | 31 | -------------------------------------------------------------------------------- /routes/carts.js: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import Cart from "../models/carts.js"; 3 | // In-memory cart storage for simplicity (use database for production) 4 | 5 | 6 | const router=new Router() 7 | router.get('/', async(req,res, next)=>{ 8 | 9 | try { 10 | const carts = await Cart.find(); 11 | 12 | if (carts) { 13 | res.json({ carts }); 14 | console.log(carts) 15 | } else { 16 | res.json({ message: "No products in cart" }); 17 | } 18 | } catch (error) { 19 | next(error); 20 | } 21 | } 22 | ); 23 | 24 | 25 | router.post("/", async (req, res, next) => { 26 | console.log(req.body); 27 | const newCart = await Cart.create(req.body); 28 | if (newCart) { 29 | res.status(201).json({ carts: newCart }); 30 | } else { 31 | res.status(400).json({ message: "Error adding new product" }); 32 | } 33 | 34 | }); 35 | 36 | 37 | router.delete('/:id', async (req,res)=>{ 38 | try{ 39 | const deleteProduct= await Cart.findByIdAndDelete(req.params.id) 40 | if (!deleteCart){ 41 | return res.send(`User not fund ${id}`)} 42 | else{res.send( 43 | { 44 | deletedCart: deleteProduct, 45 | message: "Product Deleted!" 46 | } 47 | ) 48 | }} 49 | catch(error){console.log(error)} 50 | }) 51 | 52 | router.put('/:id', async (req,res)=>{ 53 | try{ 54 | const updateCart=await Cart.findByIdAndUpdate(req.params.id, req.body, {new:true}) 55 | res.send(updateCart) 56 | console.log(updateCart) 57 | } 58 | catch(error){console.log(error)} 59 | }) 60 | 61 | export default router -------------------------------------------------------------------------------- /routes/products.js: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import Product from "../models/products.js"; 3 | 4 | 5 | const router=new Router() 6 | router.get('/', async(req,res, next)=>{ 7 | 8 | try { 9 | const products = await Product.find(); 10 | 11 | if (products) { 12 | res.json({ products }); 13 | console.log(Product) 14 | } else { 15 | res.json({ message: "No products found" }); 16 | } 17 | } catch (error) { 18 | next(error); 19 | } 20 | } 21 | ); 22 | 23 | 24 | router.get('/:id',async (req,res)=>{ 25 | try{ 26 | const product=await Product.findById(req.params.id) 27 | if (product) { 28 | res.json({product}); 29 | }else{ 30 | res.json({message:`No product found ${req.params.id}`}) 31 | } 32 | 33 | }catch(error){ 34 | console.log(error) 35 | } 36 | 37 | }) 38 | 39 | router.post("/", async (req, res, next) => { 40 | console.log(req.body); 41 | try { 42 | const newProduct = await Product.create(req.body); 43 | if (newProduct) { 44 | res.status(201).json({ product: newProduct }); 45 | } else { 46 | res.status(400).json({ message: "Error creating new product" }); 47 | } 48 | } catch (error) { 49 | next(error); 50 | } 51 | }); 52 | 53 | 54 | router.delete('/:id', async (req,res)=>{ 55 | try{ 56 | const deleteProduct= await Product.findByIdAndDelete(req.params.id) 57 | if (!deleteProduct){ 58 | return res.send(`User not fund ${id}`)} 59 | else{res.send( 60 | { 61 | deletedUser: deleteProduct, 62 | message: "Product Deleted!" 63 | } 64 | ) 65 | }} 66 | catch(error){console.log(error)} 67 | }) 68 | 69 | router.put('/:id', async (req,res)=>{ 70 | try{ 71 | const updateProduct=await Product.findByIdAndUpdate(req.params.id, req.body, {new:true}) 72 | res.send(updateProduct) 73 | console.log(updateProduct) 74 | } 75 | catch(error){console.log(error)} 76 | }) 77 | 78 | export default router -------------------------------------------------------------------------------- /routes/users.js: -------------------------------------------------------------------------------- 1 | import User from "../models/users.js"; 2 | 3 | import {Router} from 'express' 4 | 5 | const router=new Router 6 | 7 | const data=[ 8 | {username:'user1', 9 | emailaddress:'user1@gmail.com', 10 | }, 11 | 12 | {username:'user2', 13 | emailaddress:'user2@gmail.com', 14 | }, 15 | 16 | {username:'user3', 17 | emailaddress:'user3@gmail.com', 18 | }, 19 | ] 20 | 21 | 22 | 23 | router.get('/', async(req,res, next)=>{ 24 | 25 | try { 26 | const Users = await User.find(); 27 | 28 | if (Users) { 29 | res.json({ Users }); 30 | console.log(Users) 31 | } else { 32 | res.json({ message: "No users found" }); 33 | } 34 | } catch (error) { 35 | next(error); 36 | } 37 | } 38 | ); 39 | 40 | 41 | router.get('/:id',async (req,res)=>{ 42 | try{ 43 | const user=await User.findById(req.params.id) 44 | if (user) { 45 | res.json({user}); 46 | }else{ 47 | res.json({message:`No user found ${req.params.id}`}) 48 | } 49 | }catch(error){ 50 | console.log(error) 51 | } 52 | 53 | }) 54 | 55 | router.post("/", async (req, res, next) => { 56 | console.log(req.body); 57 | try { 58 | const newUser = await User.create(req.body); 59 | if (newUser) { 60 | res.status(201).json({ user: newUser }); 61 | } else { 62 | res.status(400).json({ message: "Error creating new user" }); 63 | } 64 | } catch (error) { 65 | next(error); 66 | } 67 | }); 68 | 69 | 70 | router.delete('/:id', async (req,res)=>{ 71 | try{ 72 | const deleteUser= await User.findByIdAndDelete(req.params.id) 73 | if (!deleteUser){ 74 | return res.send(`User not fund ${id}`)} 75 | else{res.send( 76 | { 77 | deletedUser: deleteUser, 78 | message: "User Deleted!" 79 | } 80 | ) 81 | }} 82 | catch(error){console.log(error)} 83 | }) 84 | 85 | router.put('/:id', async (req,res)=>{ 86 | try{ 87 | const updateUser=await User.findByIdAndUpdate(req.params.id, req.body, {new:true}) 88 | res.send(updateUser) 89 | console.log(updateUser) 90 | } 91 | catch(error){console.log(error)} 92 | }) 93 | 94 | export default router -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import ProductsRouter from "./routes/products.js"; 3 | import UsersRouter from "./routes/users.js"; 4 | import CartRouter from "./routes/carts.js"; 5 | import StripeRouter from "./routes/checkout.js"; 6 | import mongoose from "mongoose"; 7 | import dotenv from "dotenv"; 8 | import morgan from "morgan"; 9 | import cors from "cors"; 10 | import { Stripe } from "stripe"; 11 | import Cart from "./models/carts.js"; 12 | dotenv.config(); 13 | const app = express(); 14 | const PORT = process.env.PORT || 3000; 15 | // =======connect to DataBase =========== 16 | try { 17 | await mongoose.connect(process.env.MONGODB_URI); 18 | console.log(`Connected to MONGODB`); 19 | } catch (error) { 20 | console.error(error); 21 | } 22 | 23 | // In-memory cart storage for simplicity (use database for production) 24 | app.set("view engine", "pug"); 25 | app.set("views", "./views"); 26 | 27 | app.use(express.json()); 28 | app.use(morgan("dev")); //logger 29 | app.use(cors()); 30 | app.use(express.urlencoded({ extended: true })); 31 | app.use(express.static("public")); 32 | app.use(express.urlencoded({ extended: true })); 33 | app.get("/", (req, res) => { 34 | res.send(`welcome to my API`); 35 | }); 36 | 37 | // app.get('/about', (req, res) =>{ 38 | // res.render('about.pug')}) 39 | // app.get('/return', (req, res) =>{ 40 | // res.render('return.pug')}) 41 | 42 | app.use("/users", UsersRouter); 43 | app.use("/carts", CartRouter); 44 | app.use("/products", ProductsRouter); 45 | 46 | app.post("/create-checkout-session", async (req, res,next) => { 47 | 48 | 49 | // res.json({url:"apple"}) 50 | // console.log(req.body) 51 | // const storeItems = new Map([ 52 | // [1, { priceInCents: 10000, name: "Learn React Today" }], 53 | // [2, { priceInCents: 20000, name: "CSS HTML" }], 54 | // ]); 55 | const stripe = new Stripe(process.env.STRIPE_PRIVATE_KEY); 56 | // console.log(process.env.STRIPE_PRIVATE_KEY); 57 | // try{ const cartsItem = await Cart.find(); 58 | // if (cartsItem){ 59 | // console.log(cartsItem); 60 | // } else { 61 | // res.json({message:" No item in cart"}); 62 | // } 63 | // }catch (error){next(error)} 64 | try { 65 | const cartsItem = await Cart.find(); 66 | console.log(req.body) 67 | const session = await stripe.checkout.sessions.create({ 68 | payment_method_types: ["card"], 69 | mode: "payment", 70 | // line_items: req.body.items?.map(item=>{const storeItem=storeItems.get(item.id) 71 | // return{ 72 | // price_data:{ 73 | // product_data:{ 74 | // name:storeItem.name 75 | // }, 76 | // unit_amount: storeItem.priceIncents 77 | // }, 78 | // quantity:item.quantity 79 | // } 80 | // }), 81 | 82 | line_items: [ 83 | // cartsItem?.map(item => { 84 | // const cartItem = cartsItem.get(item); 85 | // console.log(req.body.items) 86 | // return 87 | { 88 | price_data: { 89 | currency: "usd", 90 | product_data: {name: cartsItem[1].name}, 91 | unit_amount: cartsItem[1].price*100, 92 | }, 93 | quantity: 1, 94 | }, 95 | ], 96 | // }), 97 | 98 | success_url: 'http://localhost:3000/success.html', 99 | cancel_url: 'http://localhost:3000/cancel.html', 100 | // success_url: "${process.env.SERVER_URL}/success.html", 101 | // cancel_url: "${process.env.SERVER_URL}/cancel.html ", 102 | 103 | }) 104 | res.json({ url: session.url }); 105 | } catch (e) { 106 | res.status(500).json({ error: e.message }); 107 | } 108 | }); 109 | 110 | //=========Error Middleware====== 111 | app.use((e, req, res, next) => { 112 | console.error(e); 113 | res.status(500).json({ message: e.message, error: e }); 114 | }); 115 | 116 | app.listen(PORT, () => console.log(`Server at ${PORT}`)); 117 | --------------------------------------------------------------------------------