From 04635f9ddf3e9dfc0c934189dba3f18080467440 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Tue, 14 Jan 2020 01:12:16 +0530 Subject: [PATCH 01/50] adding controllers --- app.js | 7 ++----- controller/products.js | 16 ++++++++++++++++ routes/admin.js | 19 ++++++------------- routes/shop.js | 12 ++---------- views/shop.ejs | 10 ---------- 5 files changed, 26 insertions(+), 38 deletions(-) create mode 100644 controller/products.js diff --git a/app.js b/app.js index d6a0724..436b9d6 100644 --- a/app.js +++ b/app.js @@ -3,27 +3,24 @@ const path = require('path'); const express = require('express'); const bodyParser = require('body-parser'); -const adminData = require('./routes/admin'); +const adminRoutes = require('./routes/admin'); const shopRoutes = require('./routes/shop'); const rootDir = require('./util/path'); const app = express(); -// no need to register the engin, as exoress auto register it app.set('view engine', 'ejs'); app.set('views', 'views'); app.use(bodyParser.urlencoded({extended : true})); app.use(express.static(path.join(rootDir, 'public'))); -app.use('/admin',adminData.routes); +app.use('/admin', adminRoutes); app.use(shopRoutes); app.use((req, res, next) => { res.status(404); res.setHeader('Content-type','text/html'); - // passing the argument to templating engine doesnt change, it remains the same - // "path: 'Error'" we passed becasue ejs engin will check "path" argument in naviagation bar logic of template. if we will not provide, we will get an error res.render('404', {pageTitle: "404", path: 'Error'}); }); diff --git a/controller/products.js b/controller/products.js new file mode 100644 index 0000000..2b3323e --- /dev/null +++ b/controller/products.js @@ -0,0 +1,16 @@ +const products = []; + +exports.getAddProduct = (req, res, next) => { + res.render('addProduct', {path: "admin/add-product", pageTitle : 'Add Products', activeAddProduct: true, formsCSS: true, productCSS: true}) +}; + +exports.postAddProduct = (req, res, next) => { + products.push({'title' : req.body.title}); + console.log('admin.js ', products); + res.redirect('/'); +}; + +exports.getproduct = (req, res, next) => { + res.render('shop', {pageTitle: 'Shop', prods : products, path : '/'}); + // console.log('shop.js ', products); +}; \ No newline at end of file diff --git a/routes/admin.js b/routes/admin.js index 259e70e..c3fe8e1 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -1,22 +1,15 @@ - const path = require('path'); const express = require('express'); -const rootDir = require('../util/path'); +// no more using html pages, as we are using ejs engine +// const rootDir = require('../util/path'); +const productsController = require('../controller/products'); const routes = express.Router(); -const products = []; -routes.get('/add-product', (req, res, next) => { - res.render('addProduct', {path: "admin/add-product", pageTitle : 'Add Products', activeAddProduct: true, formsCSS: true, productCSS: true}) -}); +routes.get('/add-product', productsController.getAddProduct); -routes.post('/add-product', (req, res, next) => { - products.push({'title' : req.body.title}); - console.log('admin.js ', products); - res.redirect('/'); -}); +routes.post('/add-product', productsController.postAddProduct); -module.exports.routes = routes; -module.exports.productArr = products; \ No newline at end of file +module.exports = routes; diff --git a/routes/shop.js b/routes/shop.js index a558eea..fb40926 100644 --- a/routes/shop.js +++ b/routes/shop.js @@ -2,18 +2,10 @@ const path = require('path'); const express = require('express'); -const adminData = require('./admin'); +const productsController = require('../controller/products'); const routes = express.Router(); -routes.get('/', (req, res, next) => { - // "layout: false" is speacial keyword which is understood by handlerbars which tells us that we are not using anhy layouts. thus no error regarding layouts will pop up. - // res.render('shop', {pageTitle: 'Shop', prods : adminData.productArr, path : '/', hasProducts : adminData.productArr.length > 0, layout: false}); - - res.render('shop', {pageTitle: 'Shop', prods : adminData.productArr, path : '/', hasProducts : adminData.productArr.length > 0, activeShop: true, productCSS: true}); - - console.log('shop.js ', adminData.productArr); -}); +routes.get('/', productsController.getproduct); module.exports = routes; - diff --git a/views/shop.ejs b/views/shop.ejs index ca4ba38..4a09fce 100644 --- a/views/shop.ejs +++ b/views/shop.ejs @@ -1,24 +1,14 @@ - - - - <%- include('./includes/head.ejs') %> <%- include('./includes/navigation.ejs') %>
- - - <% if (prods.length > 0) { %>
- <% for (let product of prods) { %>
- -

<%= product.title %>

From 3b3ca6333a31aef6472fffb0b5a07d9698c61704 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Tue, 14 Jan 2020 19:18:42 +0530 Subject: [PATCH 02/50] added error controller --- app.js | 7 ++----- controller/error.js | 5 +++++ 2 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 controller/error.js diff --git a/app.js b/app.js index 436b9d6..9d9f444 100644 --- a/app.js +++ b/app.js @@ -6,6 +6,7 @@ const bodyParser = require('body-parser'); const adminRoutes = require('./routes/admin'); const shopRoutes = require('./routes/shop'); const rootDir = require('./util/path'); +const errorController = require('./controller/error'); const app = express(); @@ -18,10 +19,6 @@ app.use(express.static(path.join(rootDir, 'public'))); app.use('/admin', adminRoutes); app.use(shopRoutes); -app.use((req, res, next) => { - res.status(404); - res.setHeader('Content-type','text/html'); - res.render('404', {pageTitle: "404", path: 'Error'}); -}); +app.use(errorController.get404); app.listen(3000); \ No newline at end of file diff --git a/controller/error.js b/controller/error.js new file mode 100644 index 0000000..45d2ef3 --- /dev/null +++ b/controller/error.js @@ -0,0 +1,5 @@ +exports.get404 = (req, res, next) => { + res.status(404); + res.setHeader('Content-type','text/html'); + res.render('404', {pageTitle: "404", path: 'Error'}); +}; \ No newline at end of file From 73b9acfd4d06b3e3259fdec67883d64f9b9249c6 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 09:30:38 +0530 Subject: [PATCH 03/50] adding product model --- app.js | 4 ++-- controller/error.js | 4 ++-- controller/products.js | 38 +++++++++++++++++++++++++++++++------- model/product.js | 39 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 model/product.js diff --git a/app.js b/app.js index 9d9f444..a99b7ef 100644 --- a/app.js +++ b/app.js @@ -1,4 +1,4 @@ -const path = require('path'); +const path = require('path'); const express = require('express'); const bodyParser = require('body-parser'); @@ -13,7 +13,7 @@ const app = express(); app.set('view engine', 'ejs'); app.set('views', 'views'); -app.use(bodyParser.urlencoded({extended : true})); +app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static(path.join(rootDir, 'public'))); app.use('/admin', adminRoutes); diff --git a/controller/error.js b/controller/error.js index 45d2ef3..5d3d895 100644 --- a/controller/error.js +++ b/controller/error.js @@ -1,5 +1,5 @@ exports.get404 = (req, res, next) => { res.status(404); - res.setHeader('Content-type','text/html'); - res.render('404', {pageTitle: "404", path: 'Error'}); + res.setHeader('Content-type', 'text/html'); + res.render('404', { pageTitle: "404", path: 'Error' }); }; \ No newline at end of file diff --git a/controller/products.js b/controller/products.js index 2b3323e..26334b4 100644 --- a/controller/products.js +++ b/controller/products.js @@ -1,16 +1,40 @@ -const products = []; +// no need of this, we have our "model" file +// const products = []; + +// Product(P is uppercase), this is because it is convention to use class variable with upper case +const Product = require("../model/product"); + +// now we willcreate a new object based on class blueprint exports.getAddProduct = (req, res, next) => { - res.render('addProduct', {path: "admin/add-product", pageTitle : 'Add Products', activeAddProduct: true, formsCSS: true, productCSS: true}) + res.render("addProduct", { + path: "admin/add-product", + pageTitle: "Add Products", + activeAddProduct: true, + formsCSS: true, + productCSS: true + }); }; exports.postAddProduct = (req, res, next) => { - products.push({'title' : req.body.title}); - console.log('admin.js ', products); - res.redirect('/'); + // no use, we will create new object to the class and pass the value to it + // products.push({'title' : req.body.title}); + + // in form field of 'addProduct.ejs' , there "name= title". thus writing "req.body.title" + const product = new Product(req.body.title); + product.save(); + + // after craeting the new product object, we need to save that by calling save() method of the clas + console.log("admin.js ", product); + res.redirect("/"); }; exports.getproduct = (req, res, next) => { - res.render('shop', {pageTitle: 'Shop', prods : products, path : '/'}); + // we are just calling static method and not craeting any object with dummy text, as we alraedy have an product array in 'model' where we are storing all the products + const products = Product.fetchAll(); + res.render("shop", { + pageTitle: "Shop", + prods: products, path: "/" + }); // console.log('shop.js ', products); -}; \ No newline at end of file +}; diff --git a/model/product.js b/model/product.js new file mode 100644 index 0000000..8aa8fb2 --- /dev/null +++ b/model/product.js @@ -0,0 +1,39 @@ +// ES5 way +// module.exports = function Product() {} + + +const products = []; + +// ES6 : using concept of classes +module.exports = class Product { + + // constructor is used to give shape to the product + constructor(t) { + // creating a property within a class "title" + // this allows us to create an object based in this class where we can pass the ttitle to the constructor, which we call with new and then this will get stored in created object + // but we dont only create the object + this.title = t; + } + + // but we want to store the product to our array product and fetch it when nessary + + // "save" is special function without a 'function' keyword + // save method is avaliable in the class where we will save the products + + // "save()" should be called on instatited object pased on object + save() { + // "this" will reffer to the object created within a class, and that object we want to push to the product array + products.push(this); + } + + // after saving, we should able to retrive the products from the array product + // "fetchAll" method is like utility function. this is not called on single instance of the product because because it should fetch all products and we dont want to create new object with new keyword with some dummy title, just to fech all existence product. + // thus we will add "static " keyword, which make sure that we call this method directly on the class itself and no on any instanttiated object + static fetchAll() { + // "this.product" will return the current product and not the full array of products + // return this.product; + + // we should return whole product array + return products; + } +} \ No newline at end of file From 865cba4cb7aed8f7453453ced4bb4c72f4cdb7b8 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 11:25:56 +0530 Subject: [PATCH 04/50] storing data in a file via model --- controller/products.js | 13 ------ data/products.json | 1 + model/product.js | 94 ++++++++++++++++++++++++++++++++---------- 3 files changed, 73 insertions(+), 35 deletions(-) create mode 100644 data/products.json diff --git a/controller/products.js b/controller/products.js index 26334b4..6ae5786 100644 --- a/controller/products.js +++ b/controller/products.js @@ -1,11 +1,5 @@ -// no need of this, we have our "model" file -// const products = []; - -// Product(P is uppercase), this is because it is convention to use class variable with upper case const Product = require("../model/product"); -// now we willcreate a new object based on class blueprint - exports.getAddProduct = (req, res, next) => { res.render("addProduct", { path: "admin/add-product", @@ -17,24 +11,17 @@ exports.getAddProduct = (req, res, next) => { }; exports.postAddProduct = (req, res, next) => { - // no use, we will create new object to the class and pass the value to it - // products.push({'title' : req.body.title}); - - // in form field of 'addProduct.ejs' , there "name= title". thus writing "req.body.title" const product = new Product(req.body.title); product.save(); - // after craeting the new product object, we need to save that by calling save() method of the clas console.log("admin.js ", product); res.redirect("/"); }; exports.getproduct = (req, res, next) => { - // we are just calling static method and not craeting any object with dummy text, as we alraedy have an product array in 'model' where we are storing all the products const products = Product.fetchAll(); res.render("shop", { pageTitle: "Shop", prods: products, path: "/" }); - // console.log('shop.js ', products); }; diff --git a/data/products.json b/data/products.json new file mode 100644 index 0000000..8b086a0 --- /dev/null +++ b/data/products.json @@ -0,0 +1 @@ +[{"title":"book"}] \ No newline at end of file diff --git a/model/product.js b/model/product.js index 8aa8fb2..40bc28c 100644 --- a/model/product.js +++ b/model/product.js @@ -1,39 +1,89 @@ -// ES5 way -// module.exports = function Product() {} +// no more array, as we will store all our products in a file +// const products = []; +const fs = require('fs'); +const path = require('path'); -const products = []; +const rootDir = require('../util/path'); -// ES6 : using concept of classes module.exports = class Product { - // constructor is used to give shape to the product constructor(t) { - // creating a property within a class "title" - // this allows us to create an object based in this class where we can pass the ttitle to the constructor, which we call with new and then this will get stored in created object - // but we dont only create the object this.title = t; } + save() { + // no more pushing elements to array + // products.push(this); - // but we want to store the product to our array product and fetch it when nessary + // creating a file + // if u dont want to use, "path" file which is in util folder, directly use the command, which we have provided in "path" file of util folder + // const p = path.join(path.dirname(process.mainModule.filename), 'data', 'products.json'); - // "save" is special function without a 'function' keyword - // save method is avaliable in the class where we will save the products + // we will store file in JSON format + const p = path.join(rootDir, 'data', 'products.json') - // "save()" should be called on instatited object pased on object - save() { - // "this" will reffer to the object created within a class, and that object we want to push to the product array - products.push(this); + // to store the new product, first we need to get existing products and then store new product at the end + // so, first we read the file + // for large file, we will not read file.ie, not putting the file in memory. we will be reading as a stream + // fs.createReadStream() + + // but our file will be shorter, we will read the file + // function in second argument will be executed when reading of file is done + fs.readFile(p, (err, fileContent) => { + // console.log(fileContent); + + //if we run the server, we will get + // ReferenceError: products is not defined at "shop.js" + // we got an error because, we dont have any file... so no content + + // now, if we see error + // console.log(err); + // in console, we can see + // "undefined" + // [Error: ENOENT: no such file or directory, open 'D:\My\vscode\node\5.express\data\products.json'] { + // errno: -4058, + // code: 'ENOENT', + // syscall: 'open', + // path: 'D:\\My\\vscode\\node\\5.express\\data\\products.json' + // } + + + let products = []; + if (!err) { + // parse method will takes incoming JSON data and gives back js array or object or whatever is there in a file + products = JSON.parse(fileContent); + } + // as we are using arrow function, it will reffer to the class. if we will use "function"(es5), it will losse its context and will not reffer to the class + // "this" refferes to the current object of the class + products.push(this); + + // after pushing to array, now we should save it to the file + // "stringify" method will take js object/arary and convert it into JSON format + fs.writeFile(p, JSON.stringify(products), (err) => { + console.log(err); + // we will still get an error, as we are not outputting anything. but we get + // "null" + // but in data folder, "products.json" is craeted where we can see the one object created in form of JSON + + }); + }) } - // after saving, we should able to retrive the products from the array product - // "fetchAll" method is like utility function. this is not called on single instance of the product because because it should fetch all products and we dont want to create new object with new keyword with some dummy title, just to fech all existence product. - // thus we will add "static " keyword, which make sure that we call this method directly on the class itself and no on any instanttiated object static fetchAll() { - // "this.product" will return the current product and not the full array of products - // return this.product; + const p = path.join(rootDir, 'data', 'products.json') + + // after stroing it in file, we should reterive the data + fs.readFile(p, (err, fileContent) => { + if(err) { + // if error is there, it will simply gives empty array and comes out of function + return []; + } + // convert json to JS form and pront it out + return JSON.parse(fileContent); + }); - // we should return whole product array - return products; + // running the server, we get + // Cannot read property 'length' of undefined + // this error can be hard to debug } } \ No newline at end of file From 42d76e4c141abc7c7248a3b39768a891d291346d Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 13:46:50 +0530 Subject: [PATCH 05/50] Fetching Data from Files Via the Model --- controller/products.js | 23 ++++++++--- data/products.json | 2 +- model/product.js | 94 ++++++++++++++++-------------------------- routes/shop.js | 2 +- 4 files changed, 54 insertions(+), 67 deletions(-) diff --git a/controller/products.js b/controller/products.js index 6ae5786..f9626a2 100644 --- a/controller/products.js +++ b/controller/products.js @@ -18,10 +18,21 @@ exports.postAddProduct = (req, res, next) => { res.redirect("/"); }; -exports.getproduct = (req, res, next) => { - const products = Product.fetchAll(); - res.render("shop", { - pageTitle: "Shop", - prods: products, path: "/" - }); +// no we will pass our fuction, where we will get our product +exports.getProduct = (req, res, next) => { + // no need to store, as fetchAll will not return anything + // const products = Product.fetchAll(); + + Product.fetchAll((products) => { + // instead of that, we will crete our own callback process, and we render in that function, where we pass it to fetchAll(). + // once i know that fetching all the product is done, and we recieve the product here because that is exactly the argument, we passed to callback. + + // "cb" argument will reffer to this anonmous function + res.render("shop", { + pageTitle: "Shop", + prods: products, path: "/" + }); + }) }; + +// expaliation: we have fetchAll() which takes function as an argument, which should executes once it done. once it done, it will get a product and then we render our response with taht product diff --git a/data/products.json b/data/products.json index 8b086a0..a16de37 100644 --- a/data/products.json +++ b/data/products.json @@ -1 +1 @@ -[{"title":"book"}] \ No newline at end of file +[{"title":"book"},{"title":"fds"}] \ No newline at end of file diff --git a/model/product.js b/model/product.js index 40bc28c..f75eea5 100644 --- a/model/product.js +++ b/model/product.js @@ -1,6 +1,3 @@ -// no more array, as we will store all our products in a file -// const products = []; - const fs = require('fs'); const path = require('path'); @@ -12,78 +9,57 @@ module.exports = class Product { this.title = t; } save() { - // no more pushing elements to array - // products.push(this); - - // creating a file - // if u dont want to use, "path" file which is in util folder, directly use the command, which we have provided in "path" file of util folder - // const p = path.join(path.dirname(process.mainModule.filename), 'data', 'products.json'); - - // we will store file in JSON format const p = path.join(rootDir, 'data', 'products.json') - - // to store the new product, first we need to get existing products and then store new product at the end - // so, first we read the file - // for large file, we will not read file.ie, not putting the file in memory. we will be reading as a stream - // fs.createReadStream() - - // but our file will be shorter, we will read the file - // function in second argument will be executed when reading of file is done + let products = []; fs.readFile(p, (err, fileContent) => { - // console.log(fileContent); - - //if we run the server, we will get - // ReferenceError: products is not defined at "shop.js" - // we got an error because, we dont have any file... so no content - - // now, if we see error - // console.log(err); - // in console, we can see - // "undefined" - // [Error: ENOENT: no such file or directory, open 'D:\My\vscode\node\5.express\data\products.json'] { - // errno: -4058, - // code: 'ENOENT', - // syscall: 'open', - // path: 'D:\\My\\vscode\\node\\5.express\\data\\products.json' - // } - - - let products = []; if (!err) { - // parse method will takes incoming JSON data and gives back js array or object or whatever is there in a file products = JSON.parse(fileContent); } - // as we are using arrow function, it will reffer to the class. if we will use "function"(es5), it will losse its context and will not reffer to the class - // "this" refferes to the current object of the class - products.push(this); - - // after pushing to array, now we should save it to the file - // "stringify" method will take js object/arary and convert it into JSON format + products.push(this); + fs.writeFile(p, JSON.stringify(products), (err) => { console.log(err); - // we will still get an error, as we are not outputting anything. but we get - // "null" - // but in data folder, "products.json" is craeted where we can see the one object created in form of JSON - + }); }) + } - static fetchAll() { + // this function is running asyn code + // it will store both the function but will not execute 1.const p = path.join 2.fs.readFile(p, (err, fileContent), thus function does not return anything + // hence, undefined will be passed from fetchAll(). thus in "shop.ejs", after passing value to shop.ejs. our condition becaome (undefined.length > 0) + + // static fetchAll() { + // const p = path.join(rootDir, 'data', 'products.json') + + // fs.readFile(p, (err, fileContent) => { + // if(err) { + // return []; + // } + // return JSON.parse(fileContent); + // }); + + // FIX + // more info on callback handling: https://www.youtube.com/watch?v=jgWnccjXR4I + // we are passing callback function, that actually allows me to pass a function into fetchAll() which fechAll will execute once it is done, so that thing calling fetchAll() can pass a function. it is then aware of being called which holds the data, we want to return + + //1. so we are reciving a function(cb), this argument will hold a function + static fetchAll(cb) { const p = path.join(rootDir, 'data', 'products.json') - // after stroing it in file, we should reterive the data + // expalation: readfile also takes a callback,we pass the fuction, which should be executed once it is done fs.readFile(p, (err, fileContent) => { - if(err) { - // if error is there, it will simply gives empty array and comes out of function - return []; - } - // convert json to JS form and pront it out - return JSON.parse(fileContent); - }); - + if(err) { + // 2.and therefoe instaed of returning an array, here we will execute callback function, which will pass empty array + cb([]); + } + // 3. same as step 2 + cb(JSON.parse(fileContent)); + }); // running the server, we get // Cannot read property 'length' of undefined // this error can be hard to debug + + } } \ No newline at end of file diff --git a/routes/shop.js b/routes/shop.js index fb40926..14e23be 100644 --- a/routes/shop.js +++ b/routes/shop.js @@ -6,6 +6,6 @@ const productsController = require('../controller/products'); const routes = express.Router(); -routes.get('/', productsController.getproduct); +routes.get('/', productsController.getProduct); module.exports = routes; From 603f66e8bd9d6f8a5018abd743620d4b686b023e Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 14:06:39 +0530 Subject: [PATCH 06/50] 099 Refactoring the File Storage Code --- controller/products.js | 9 ------ data/products.json | 2 +- model/product.js | 72 ++++++++++++++++-------------------------- 3 files changed, 28 insertions(+), 55 deletions(-) diff --git a/controller/products.js b/controller/products.js index f9626a2..7ea184c 100644 --- a/controller/products.js +++ b/controller/products.js @@ -18,16 +18,8 @@ exports.postAddProduct = (req, res, next) => { res.redirect("/"); }; -// no we will pass our fuction, where we will get our product exports.getProduct = (req, res, next) => { - // no need to store, as fetchAll will not return anything - // const products = Product.fetchAll(); - Product.fetchAll((products) => { - // instead of that, we will crete our own callback process, and we render in that function, where we pass it to fetchAll(). - // once i know that fetching all the product is done, and we recieve the product here because that is exactly the argument, we passed to callback. - - // "cb" argument will reffer to this anonmous function res.render("shop", { pageTitle: "Shop", prods: products, path: "/" @@ -35,4 +27,3 @@ exports.getProduct = (req, res, next) => { }) }; -// expaliation: we have fetchAll() which takes function as an argument, which should executes once it done. once it done, it will get a product and then we render our response with taht product diff --git a/data/products.json b/data/products.json index a16de37..9d200e9 100644 --- a/data/products.json +++ b/data/products.json @@ -1 +1 @@ -[{"title":"book"},{"title":"fds"}] \ No newline at end of file +[{"title":"book"},{"title":"fds"},{"title":"dfgh"},{"title":""},{"title":""}] \ No newline at end of file diff --git a/model/product.js b/model/product.js index f75eea5..04cee55 100644 --- a/model/product.js +++ b/model/product.js @@ -3,63 +3,45 @@ const path = require('path'); const rootDir = require('../util/path'); -module.exports = class Product { +// now we will refactore the code, ie reuse the code(or improve the exisiting code) +const p = path.join(rootDir, 'data', 'products.json'); + +// craerting common function to extrat data from file +const getProductsFromFile = (cb) => { + fs.readFile(p, (err, fileContent) => { + // as we want only one command to exetue based on condition, not both + // if(err) { + // cb([]); + // } else { + // cb(JSON.parse(fileContent)); + // } + // OR + if(err) { + return cb([]); + } + return cb(JSON.parse(fileContent)); + + }); +} + +module.exports = class Product { + constructor(t) { this.title = t; } + save() { - const p = path.join(rootDir, 'data', 'products.json') - let products = []; - fs.readFile(p, (err, fileContent) => { - if (!err) { - products = JSON.parse(fileContent); - } - products.push(this); + getProductsFromFile((products) => { + products.push(this); fs.writeFile(p, JSON.stringify(products), (err) => { console.log(err); - }); }) - } - // this function is running asyn code - // it will store both the function but will not execute 1.const p = path.join 2.fs.readFile(p, (err, fileContent), thus function does not return anything - // hence, undefined will be passed from fetchAll(). thus in "shop.ejs", after passing value to shop.ejs. our condition becaome (undefined.length > 0) - - // static fetchAll() { - // const p = path.join(rootDir, 'data', 'products.json') - - // fs.readFile(p, (err, fileContent) => { - // if(err) { - // return []; - // } - // return JSON.parse(fileContent); - // }); - - // FIX - // more info on callback handling: https://www.youtube.com/watch?v=jgWnccjXR4I - // we are passing callback function, that actually allows me to pass a function into fetchAll() which fechAll will execute once it is done, so that thing calling fetchAll() can pass a function. it is then aware of being called which holds the data, we want to return - - //1. so we are reciving a function(cb), this argument will hold a function static fetchAll(cb) { - const p = path.join(rootDir, 'data', 'products.json') - - // expalation: readfile also takes a callback,we pass the fuction, which should be executed once it is done - fs.readFile(p, (err, fileContent) => { - if(err) { - // 2.and therefoe instaed of returning an array, here we will execute callback function, which will pass empty array - cb([]); - } - // 3. same as step 2 - cb(JSON.parse(fileContent)); - }); - // running the server, we get - // Cannot read property 'length' of undefined - // this error can be hard to debug - - + getProductsFromFile(cb); } } \ No newline at end of file From f8926eda4b926d087b43863a10bee2e838a9de94 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 14:28:28 +0530 Subject: [PATCH 07/50] 103 Creating the Shop Structure --- controller/products.js | 4 ++-- data/products.json | 2 +- views/{ => admin}/addProduct.ejs | 6 +++--- views/admin/editProduct.ejs | 0 views/admin/products.ejs | 0 views/shop/cart.ejs | 0 views/shop/checkout.ejs | 0 views/shop/index.ejs | 0 views/shop/productDetail.ejs | 0 views/{shop.ejs => shop/productList.ejs} | 6 +++--- 10 files changed, 9 insertions(+), 9 deletions(-) rename views/{ => admin}/addProduct.ejs (79%) create mode 100644 views/admin/editProduct.ejs create mode 100644 views/admin/products.ejs create mode 100644 views/shop/cart.ejs create mode 100644 views/shop/checkout.ejs create mode 100644 views/shop/index.ejs create mode 100644 views/shop/productDetail.ejs rename views/{shop.ejs => shop/productList.ejs} (89%) diff --git a/controller/products.js b/controller/products.js index 7ea184c..c26f8ad 100644 --- a/controller/products.js +++ b/controller/products.js @@ -1,7 +1,7 @@ const Product = require("../model/product"); exports.getAddProduct = (req, res, next) => { - res.render("addProduct", { + res.render("admin/addProduct", { path: "admin/add-product", pageTitle: "Add Products", activeAddProduct: true, @@ -20,7 +20,7 @@ exports.postAddProduct = (req, res, next) => { exports.getProduct = (req, res, next) => { Product.fetchAll((products) => { - res.render("shop", { + res.render("shop/productList", { pageTitle: "Shop", prods: products, path: "/" }); diff --git a/data/products.json b/data/products.json index 9d200e9..1a136b8 100644 --- a/data/products.json +++ b/data/products.json @@ -1 +1 @@ -[{"title":"book"},{"title":"fds"},{"title":"dfgh"},{"title":""},{"title":""}] \ No newline at end of file +[{"title":"book"},{"title":"fds"},{"title":"dfgh"},{"title":""},{"title":""},{"title":"book"},{"title":""}] \ No newline at end of file diff --git a/views/addProduct.ejs b/views/admin/addProduct.ejs similarity index 79% rename from views/addProduct.ejs rename to views/admin/addProduct.ejs index 7ccd3db..b68c0bf 100644 --- a/views/addProduct.ejs +++ b/views/admin/addProduct.ejs @@ -1,9 +1,9 @@ -<%- include('./includes/head.ejs') %> +<%- include('../includes/head.ejs') %> -<%- include('./includes/navigation.ejs') %> +<%- include('../includes/navigation.ejs') %>
@@ -15,4 +15,4 @@
-<%- include('./includes/end.ejs') %> \ No newline at end of file +<%- include('../includes/end.ejs') %> \ No newline at end of file diff --git a/views/admin/editProduct.ejs b/views/admin/editProduct.ejs new file mode 100644 index 0000000..e69de29 diff --git a/views/admin/products.ejs b/views/admin/products.ejs new file mode 100644 index 0000000..e69de29 diff --git a/views/shop/cart.ejs b/views/shop/cart.ejs new file mode 100644 index 0000000..e69de29 diff --git a/views/shop/checkout.ejs b/views/shop/checkout.ejs new file mode 100644 index 0000000..e69de29 diff --git a/views/shop/index.ejs b/views/shop/index.ejs new file mode 100644 index 0000000..e69de29 diff --git a/views/shop/productDetail.ejs b/views/shop/productDetail.ejs new file mode 100644 index 0000000..e69de29 diff --git a/views/shop.ejs b/views/shop/productList.ejs similarity index 89% rename from views/shop.ejs rename to views/shop/productList.ejs index 4a09fce..1efe2ac 100644 --- a/views/shop.ejs +++ b/views/shop/productList.ejs @@ -1,8 +1,8 @@ -<%- include('./includes/head.ejs') %> +<%- include('../includes/head.ejs') %> -<%- include('./includes/navigation.ejs') %> +<%- include('../includes/navigation.ejs') %>
<% if (prods.length > 0) { %>
@@ -29,4 +29,4 @@ <% } %>
-<%- include('./includes/end.ejs') %> +<%- include('../includes/end.ejs') %> From e68938832e6f4e08e1c65cea6ea50b1a65f5fd45 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 14:52:51 +0530 Subject: [PATCH 08/50] 104 Working on the Navigation --- views/includes/navigation.ejs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/views/includes/navigation.ejs b/views/includes/navigation.ejs index a0f577d..c62690a 100644 --- a/views/includes/navigation.ejs +++ b/views/includes/navigation.ejs @@ -1,11 +1,14 @@ -
- -
\ No newline at end of file +
+ +
\ No newline at end of file From e8580841af127df87b3d09235729fb9001b1aac6 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 17:36:50 +0530 Subject: [PATCH 09/50] 105 Registering the Routes --- controller/{products.js => admin.js} | 21 +++++++----------- controller/shop.js | 31 +++++++++++++++++++++++++++ data/products.json | 2 +- routes/admin.js | 7 +++--- routes/shop.js | 11 ++++++++-- views/admin/products.ejs | 7 ++++++ views/includes/navigation.ejs | 4 ++-- views/shop/cart.ejs | 7 ++++++ views/shop/index.ejs | 32 ++++++++++++++++++++++++++++ 9 files changed, 101 insertions(+), 21 deletions(-) rename controller/{products.js => admin.js} (54%) create mode 100644 controller/shop.js diff --git a/controller/products.js b/controller/admin.js similarity index 54% rename from controller/products.js rename to controller/admin.js index c26f8ad..95cface 100644 --- a/controller/products.js +++ b/controller/admin.js @@ -2,11 +2,8 @@ const Product = require("../model/product"); exports.getAddProduct = (req, res, next) => { res.render("admin/addProduct", { - path: "admin/add-product", + path: "/admin/add-product", pageTitle: "Add Products", - activeAddProduct: true, - formsCSS: true, - productCSS: true }); }; @@ -18,12 +15,10 @@ exports.postAddProduct = (req, res, next) => { res.redirect("/"); }; -exports.getProduct = (req, res, next) => { - Product.fetchAll((products) => { - res.render("shop/productList", { - pageTitle: "Shop", - prods: products, path: "/" - }); - }) -}; - +exports.getProducts = (req, res, next) => { + res.render("admin/products", { + prods: Product, + path: "/admin/products", + pageTitle: "Admin Add Products", + }); +}; \ No newline at end of file diff --git a/controller/shop.js b/controller/shop.js new file mode 100644 index 0000000..d8d82d5 --- /dev/null +++ b/controller/shop.js @@ -0,0 +1,31 @@ +const Product = require("../model/product"); + +exports.getProduct = (req, res, next) => { + Product.fetchAll((products) => { + res.render("shop/productList", { + pageTitle: "Shop Products", + prods: products, + path: "/products" + }); + }) +}; + +exports.getCart = (req, res, next) => { + res.render('shop/cart', { + pageTitle : 'Cart', + path : '/cart' + }); +}; + +exports.getIndex = (req, res, next) => { + Product.fetchAll((products) => { + res.render("shop/index", { + pageTitle: "Shop", + prods: products, + path: "/" + }); + }) +}; + + + diff --git a/data/products.json b/data/products.json index 1a136b8..cbaafd1 100644 --- a/data/products.json +++ b/data/products.json @@ -1 +1 @@ -[{"title":"book"},{"title":"fds"},{"title":"dfgh"},{"title":""},{"title":""},{"title":"book"},{"title":""}] \ No newline at end of file +[{"title":"book"},{"title":"fds"},{"title":"dfgh"},{"title":""},{"title":""},{"title":"book"},{"title":""},{"title":""}] \ No newline at end of file diff --git a/routes/admin.js b/routes/admin.js index c3fe8e1..f2eb1ca 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -4,12 +4,13 @@ const express = require('express'); // no more using html pages, as we are using ejs engine // const rootDir = require('../util/path'); -const productsController = require('../controller/products'); +const adminController = require('../controller/admin'); const routes = express.Router(); -routes.get('/add-product', productsController.getAddProduct); +routes.get('/add-product', adminController.getAddProduct); -routes.post('/add-product', productsController.postAddProduct); +routes.post('/add-product', adminController.postAddProduct); +routes.get('/products',adminController.getProducts) module.exports = routes; diff --git a/routes/shop.js b/routes/shop.js index 14e23be..14c9c31 100644 --- a/routes/shop.js +++ b/routes/shop.js @@ -2,10 +2,17 @@ const path = require('path'); const express = require('express'); -const productsController = require('../controller/products'); +const shopController = require('../controller/shop'); const routes = express.Router(); -routes.get('/', productsController.getProduct); +routes.get('/', shopController.getIndex); + +routes.get('/products', shopController.getProduct); + +routes.get('/cart', shopController.getCart); + +// routes.get('/', shopController.getProduct); + module.exports = routes; diff --git a/views/admin/products.ejs b/views/admin/products.ejs index e69de29..079bf8b 100644 --- a/views/admin/products.ejs +++ b/views/admin/products.ejs @@ -0,0 +1,7 @@ +<%- include('../includes/head.ejs') %> + +<%- include('../includes/navigation.ejs') %> + +

Admin Products

+ +<%- include('../includes/end.ejs') %> \ No newline at end of file diff --git a/views/includes/navigation.ejs b/views/includes/navigation.ejs index c62690a..01b0ccc 100644 --- a/views/includes/navigation.ejs +++ b/views/includes/navigation.ejs @@ -7,8 +7,8 @@
  • Shop
  • Products
  • Cart
  • -
  • Add Product
  • -
  • Admin Products
  • +
  • Add Product
  • +
  • Admin Products
  • \ No newline at end of file diff --git a/views/shop/cart.ejs b/views/shop/cart.ejs index e69de29..555a9a3 100644 --- a/views/shop/cart.ejs +++ b/views/shop/cart.ejs @@ -0,0 +1,7 @@ +<%- include('../includes/head.ejs') %> + +<%- include('../includes/navigation.ejs') %> + +

    Cart

    + +<%- include('../includes/end.ejs') %> \ No newline at end of file diff --git a/views/shop/index.ejs b/views/shop/index.ejs index e69de29..450f613 100644 --- a/views/shop/index.ejs +++ b/views/shop/index.ejs @@ -0,0 +1,32 @@ + +<%- include('../includes/head.ejs') %> + + +<%- include('../includes/navigation.ejs') %> +
    + <% if (prods.length > 0) { %> +
    + <% for (let product of prods) { %> +
    +
    +

    <%= product.title %>

    +
    +
    + A Book +
    +
    +

    $19.99

    +

    A very interesting book about so many even more interesting things!

    +
    +
    + +
    +
    + <% } %> +
    + <% } else { %> +

    No Products

    + <% } %> +
    + +<%- include('../includes/end.ejs') %> From 0da04e751ec6b406aa40b35459d88bba1551fba3 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 17:52:22 +0530 Subject: [PATCH 10/50] 106 Storing Product Data --- controller/admin.js | 7 ++++++- model/product.js | 9 ++++++--- public/css/forms.css | 9 ++++++--- views/admin/addProduct.ejs | 12 ++++++++++++ 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index 95cface..4703e30 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -8,7 +8,12 @@ exports.getAddProduct = (req, res, next) => { }; exports.postAddProduct = (req, res, next) => { - const product = new Product(req.body.title); + // const product = new Product(req.body.title); + const title = req.body.title; + const imageUrl = req.body.imageUrl; + const description = req.body.description; + const price = req.body.price; + const product = new Product(title, imageUrl, description, price); product.save(); console.log("admin.js ", product); diff --git a/model/product.js b/model/product.js index 04cee55..f9a0ec5 100644 --- a/model/product.js +++ b/model/product.js @@ -27,10 +27,13 @@ const getProductsFromFile = (cb) => { module.exports = class Product { - constructor(t) { - this.title = t; + constructor(title, imageUrl, description, price) { + this.title = title; + this.imageUrl = imageUrl; + this.description = description; + this.price = price; } - + save() { getProductsFromFile((products) => { products.push(this); diff --git a/public/css/forms.css b/public/css/forms.css index 81d1cdc..8284ed0 100644 --- a/public/css/forms.css +++ b/public/css/forms.css @@ -3,18 +3,21 @@ } .form-control label, -.form-control input { +.form-control input, +.form-control textarea { display: block; width: 100%; margin-bottom: 0.25rem; } -.form-control input { +.form-control input, +.form-control textarea { border: 1px solid #a1a1a1; font: inherit; border-radius: 2px; } -.form-control input:focus { +.form-control input:focus, +.form-control textarea:focus{ outline-color: #00695c; } diff --git a/views/admin/addProduct.ejs b/views/admin/addProduct.ejs index b68c0bf..e9d99e4 100644 --- a/views/admin/addProduct.ejs +++ b/views/admin/addProduct.ejs @@ -10,6 +10,18 @@
    +
    + + +
    +
    + + +
    +
    + + +
    From 8e381c4e9091445424ff1eca03f5a5472d97af06 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 17:57:02 +0530 Subject: [PATCH 11/50] comments added to existing code --- controller/admin.js | 5 +++++ model/product.js | 11 +---------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index 4703e30..a922527 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -8,11 +8,16 @@ exports.getAddProduct = (req, res, next) => { }; exports.postAddProduct = (req, res, next) => { + // no need of this, as we are storing all the aguments (title, imageUrl, description, price) and then passing it to constructor of a class, to create a new object // const product = new Product(req.body.title); + + // ".title, .imageUrl, .description, .price" should be the same name as given in form field of html page. eg: name="title" const title = req.body.title; const imageUrl = req.body.imageUrl; const description = req.body.description; const price = req.body.price; + + // arguments should be passed in same order as done in constructor const product = new Product(title, imageUrl, description, price); product.save(); diff --git a/model/product.js b/model/product.js index f9a0ec5..6c443fe 100644 --- a/model/product.js +++ b/model/product.js @@ -3,19 +3,10 @@ const path = require('path'); const rootDir = require('../util/path'); -// now we will refactore the code, ie reuse the code(or improve the exisiting code) const p = path.join(rootDir, 'data', 'products.json'); -// craerting common function to extrat data from file const getProductsFromFile = (cb) => { fs.readFile(p, (err, fileContent) => { - // as we want only one command to exetue based on condition, not both - // if(err) { - // cb([]); - // } else { - // cb(JSON.parse(fileContent)); - // } - // OR if(err) { return cb([]); } @@ -33,7 +24,7 @@ module.exports = class Product { this.description = description; this.price = price; } - + save() { getProductsFromFile((products) => { products.push(this); From 7794e39eb4d247a584d2b5eb04e1c3518f203280 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 18:15:16 +0530 Subject: [PATCH 12/50] 107 Displaying Product Data --- controller/admin.js | 7 ----- data/products.json | 2 +- views/admin/addProduct.ejs | 2 +- views/shop/index.ejs | 6 ++--- views/shop/productList.ejs | 54 +++++++++++++++++++------------------- 5 files changed, 32 insertions(+), 39 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index a922527..6dd9bd3 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -8,20 +8,13 @@ exports.getAddProduct = (req, res, next) => { }; exports.postAddProduct = (req, res, next) => { - // no need of this, as we are storing all the aguments (title, imageUrl, description, price) and then passing it to constructor of a class, to create a new object - // const product = new Product(req.body.title); - - // ".title, .imageUrl, .description, .price" should be the same name as given in form field of html page. eg: name="title" const title = req.body.title; const imageUrl = req.body.imageUrl; const description = req.body.description; const price = req.body.price; - // arguments should be passed in same order as done in constructor const product = new Product(title, imageUrl, description, price); product.save(); - - console.log("admin.js ", product); res.redirect("/"); }; diff --git a/data/products.json b/data/products.json index cbaafd1..52b3322 100644 --- a/data/products.json +++ b/data/products.json @@ -1 +1 @@ -[{"title":"book"},{"title":"fds"},{"title":"dfgh"},{"title":""},{"title":""},{"title":"book"},{"title":""},{"title":""}] \ No newline at end of file +[{"title":"book","imageUrl":"","description":"sdfgh","price":".01"}] \ No newline at end of file diff --git a/views/admin/addProduct.ejs b/views/admin/addProduct.ejs index e9d99e4..aae0b8f 100644 --- a/views/admin/addProduct.ejs +++ b/views/admin/addProduct.ejs @@ -16,7 +16,7 @@
    - +
    diff --git a/views/shop/index.ejs b/views/shop/index.ejs index 450f613..0698810 100644 --- a/views/shop/index.ejs +++ b/views/shop/index.ejs @@ -12,11 +12,11 @@

    <%= product.title %>

    - A Book + <%= product.title %>
    -

    $19.99

    -

    A very interesting book about so many even more interesting things!

    +

    <%= product.price %>

    +

    $<%= product.description %>

    diff --git a/views/shop/productList.ejs b/views/shop/productList.ejs index 1efe2ac..a0f4d13 100644 --- a/views/shop/productList.ejs +++ b/views/shop/productList.ejs @@ -1,32 +1,32 @@ <%- include('../includes/head.ejs') %> - - + + <%- include('../includes/navigation.ejs') %> -
    - <% if (prods.length > 0) { %> -
    - <% for (let product of prods) { %> -
    -
    -

    <%= product.title %>

    -
    -
    - A Book -
    -
    -

    $19.99

    -

    A very interesting book about so many even more interesting things!

    -
    -
    - -
    -
    - <% } %> -
    - <% } else { %> -

    No Products

    - <% } %> -
    +
    + <% if (prods.length > 0) { %> +
    + <% for (let product of prods) { %> +
    +
    +

    <%= product.title %>

    +
    +
    + <%= product.title %> +
    +
    +

    $<%= product.price %>

    +

    <%= product.description %>

    +
    +
    + +
    +
    + <% } %> +
    + <% } else { %> +

    No Products

    + <% } %> +
    <%- include('../includes/end.ejs') %> From 16beb58d8fa40bde6a5ed20ed4ec26be804a370c Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 18:33:25 +0530 Subject: [PATCH 13/50] 108 Editing Deleting Products --- controller/admin.js | 12 +++++++----- views/admin/products.ejs | 34 +++++++++++++++++++++++++++++++--- views/shop/index.ejs | 4 ++-- views/shop/productList.ejs | 2 ++ 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index 6dd9bd3..8698913 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -19,9 +19,11 @@ exports.postAddProduct = (req, res, next) => { }; exports.getProducts = (req, res, next) => { - res.render("admin/products", { - prods: Product, - path: "/admin/products", - pageTitle: "Admin Add Products", - }); + Product.fetchAll((products) => { + res.render("admin/products", { + path: "/admin/products", + pageTitle: "Admin Add Products", + prods: products, + }); + }) }; \ No newline at end of file diff --git a/views/admin/products.ejs b/views/admin/products.ejs index 079bf8b..1eb53da 100644 --- a/views/admin/products.ejs +++ b/views/admin/products.ejs @@ -1,7 +1,35 @@ + <%- include('../includes/head.ejs') %> + <%- include('../includes/navigation.ejs') %> +
    + <% if (prods.length > 0) { %> +
    + <% for (let product of prods) { %> +
    +
    +

    <%= product.title %>

    +
    +
    + <%= product.title %> +
    +
    +

    $<%= product.price %>

    +

    <%= product.description %>

    +
    +
    + +
    + +
    +
    +
    + <% } %> +
    + <% } else { %> +

    No Products

    + <% } %> +
    -

    Admin Products

    - -<%- include('../includes/end.ejs') %> \ No newline at end of file +<%- include('../includes/end.ejs') %> diff --git a/views/shop/index.ejs b/views/shop/index.ejs index 0698810..a0f4d13 100644 --- a/views/shop/index.ejs +++ b/views/shop/index.ejs @@ -15,8 +15,8 @@ <%= product.title %>
    -

    <%= product.price %>

    -

    $<%= product.description %>

    +

    $<%= product.price %>

    +

    <%= product.description %>

    diff --git a/views/shop/productList.ejs b/views/shop/productList.ejs index a0f4d13..2ad9134 100644 --- a/views/shop/productList.ejs +++ b/views/shop/productList.ejs @@ -19,7 +19,9 @@

    <%= product.description %>

    +
    +
    <% } %> From 43708cc16255ab10c2b1dea6c92bdaa0f9b4e748 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 18:39:25 +0530 Subject: [PATCH 14/50] 109 Adding Another Item --- controller/shop.js | 7 +++++++ routes/shop.js | 3 +-- views/admin/products.ejs | 2 +- views/includes/navigation.ejs | 1 + views/shop/orders.ejs | 7 +++++++ views/shop/productList.ejs | 2 +- 6 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 views/shop/orders.ejs diff --git a/controller/shop.js b/controller/shop.js index d8d82d5..78f4f7a 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -17,6 +17,13 @@ exports.getCart = (req, res, next) => { }); }; +exports.getOrders = (req, res, next) => { + res.render('shop/orders', { + pageTitle : 'Orders', + path : '/orders' + }); +}; + exports.getIndex = (req, res, next) => { Product.fetchAll((products) => { res.render("shop/index", { diff --git a/routes/shop.js b/routes/shop.js index 14c9c31..ea1efba 100644 --- a/routes/shop.js +++ b/routes/shop.js @@ -12,7 +12,6 @@ routes.get('/products', shopController.getProduct); routes.get('/cart', shopController.getCart); -// routes.get('/', shopController.getProduct); - +routes.get('/orders', shopController.getOrders); module.exports = routes; diff --git a/views/admin/products.ejs b/views/admin/products.ejs index 1eb53da..4eb161a 100644 --- a/views/admin/products.ejs +++ b/views/admin/products.ejs @@ -20,7 +20,7 @@
    -
    +
    diff --git a/views/includes/navigation.ejs b/views/includes/navigation.ejs index 01b0ccc..ebd3a8e 100644 --- a/views/includes/navigation.ejs +++ b/views/includes/navigation.ejs @@ -7,6 +7,7 @@
  • Shop
  • Products
  • Cart
  • +
  • Orders
  • Add Product
  • Admin Products
  • diff --git a/views/shop/orders.ejs b/views/shop/orders.ejs new file mode 100644 index 0000000..10a9d59 --- /dev/null +++ b/views/shop/orders.ejs @@ -0,0 +1,7 @@ +<%- include('../includes/head.ejs') %> + +<%- include('../includes/navigation.ejs') %> + +

    Your Orders

    + +<%- include('../includes/end.ejs') %> \ No newline at end of file diff --git a/views/shop/productList.ejs b/views/shop/productList.ejs index 2ad9134..3b083a9 100644 --- a/views/shop/productList.ejs +++ b/views/shop/productList.ejs @@ -19,7 +19,7 @@

    <%= product.description %>

    -
    +
    From b883241bcb403c7580402f6d0498cf5fc465e00d Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 18:59:21 +0530 Subject: [PATCH 15/50] adjustment made, ready for this module --- controller/admin.js | 2 +- controller/shop.js | 2 +- public/css/main.css | 104 +++++++++++++++++- public/css/product.css | 2 + public/js/main.js | 16 +++ routes/admin.js | 2 - views/404.ejs | 11 +- .../admin/{addProduct.ejs => add-product.ejs} | 15 +-- .../{editProduct.ejs => edit-product.ejs} | 0 views/admin/products.ejs | 72 ++++++------ views/includes/end.ejs | 1 + views/includes/navigation.ejs | 64 ++++++++--- views/shop/cart.ejs | 9 +- views/shop/index.ejs | 60 +++++----- views/shop/orders.ejs | 12 +- .../{productDetail.ejs => product-detail.ejs} | 0 views/shop/product-list.ejs | 41 +++++++ views/shop/productList.ejs | 34 ------ 18 files changed, 309 insertions(+), 138 deletions(-) create mode 100644 public/js/main.js rename views/admin/{addProduct.ejs => add-product.ejs} (83%) rename views/admin/{editProduct.ejs => edit-product.ejs} (100%) rename views/shop/{productDetail.ejs => product-detail.ejs} (100%) create mode 100644 views/shop/product-list.ejs delete mode 100644 views/shop/productList.ejs diff --git a/controller/admin.js b/controller/admin.js index 8698913..4a95b4e 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -1,7 +1,7 @@ const Product = require("../model/product"); exports.getAddProduct = (req, res, next) => { - res.render("admin/addProduct", { + res.render("admin/add-product", { path: "/admin/add-product", pageTitle: "Add Products", }); diff --git a/controller/shop.js b/controller/shop.js index 78f4f7a..22f81f9 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -2,7 +2,7 @@ const Product = require("../model/product"); exports.getProduct = (req, res, next) => { Product.fetchAll((products) => { - res.render("shop/productList", { + res.render("shop/product-list", { pageTitle: "Shop Products", prods: products, path: "/products" diff --git a/public/css/main.css b/public/css/main.css index 77286bb..3e3e103 100644 --- a/public/css/main.css +++ b/public/css/main.css @@ -15,16 +15,22 @@ main { margin: auto; } +form { + display: inline; +} + .main-header { width: 100%; height: 3.5rem; background-color: #00695c; padding: 0 1.5rem; + display: flex; + align-items: center; } .main-header__nav { height: 100%; - display: flex; + display: none; align-items: center; } @@ -51,6 +57,83 @@ main { color: #ffeb3b; } +.mobile-nav { + width: 30rem; + height: 100vh; + max-width: 90%; + position: fixed; + left: 0; + top: 0; + background: white; + z-index: 10; + padding: 2rem 1rem 1rem 2rem; + transform: translateX(-100%); + transition: transform 0.3s ease-out; +} + +.mobile-nav.open { + transform: translateX(0); +} + +.mobile-nav__item-list { + list-style: none; + display: flex; + flex-direction: column; + margin: 0; + padding: 0; +} + +.mobile-nav__item { + margin: 1rem; + padding: 0; +} + +.mobile-nav__item a { + text-decoration: none; + color: black; + font-size: 1.5rem; + padding: 0.5rem 2rem; +} + +.mobile-nav__item a:active, +.mobile-nav__item a:hover, +.mobile-nav__item a.active { + background: #00695c; + color: white; + border-radius: 3px; +} + +#side-menu-toggle { + border: 1px solid white; + font: inherit; + padding: 0.5rem; + display: block; + background: transparent; + color: white; + cursor: pointer; +} + +#side-menu-toggle:focus { + outline: none; +} + +#side-menu-toggle:active, +#side-menu-toggle:hover { + color: #ffeb3b; + border-color: #ffeb3b; +} + +.backdrop { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100vh; + background: rgba(0, 0, 0, 0.5); + z-index: 5; + display: none; +} + .grid { display: flex; flex-wrap: wrap; @@ -83,16 +166,19 @@ main { } .card__actions { - padding: 1rem; - text-align: center; + padding: 1rem; + text-align: center; } .card__actions button, .card__actions a { - margin: 0 0.25rem; + margin: 0 0.25rem; } .btn { + display: inline-block; + padding: 0.25rem 1rem; + text-decoration: none; font: inherit; border: 1px solid #00695c; color: #00695c; @@ -106,3 +192,13 @@ main { background-color: #00695c; color: white; } + +@media (min-width: 768px) { + .main-header__nav { + display: flex; + } + + #side-menu-toggle { + display: none; + } +} diff --git a/public/css/product.css b/public/css/product.css index 2fe37ae..2ce1a08 100644 --- a/public/css/product.css +++ b/public/css/product.css @@ -2,11 +2,13 @@ width: 20rem; max-width: 90%; margin: auto; + display: block; } .product-item { width: 20rem; max-width: 95%; + margin: 1rem; } .product__title { diff --git a/public/js/main.js b/public/js/main.js new file mode 100644 index 0000000..3d56207 --- /dev/null +++ b/public/js/main.js @@ -0,0 +1,16 @@ +const backdrop = document.querySelector('.backdrop'); +const sideDrawer = document.querySelector('.mobile-nav'); +const menuToggle = document.querySelector('#side-menu-toggle'); + +function backdropClickHandler() { + backdrop.style.display = 'none'; + sideDrawer.classList.remove('open'); +} + +function menuToggleClickHandler() { + backdrop.style.display = 'block'; + sideDrawer.classList.add('open'); +} + +backdrop.addEventListener('click', backdropClickHandler); +menuToggle.addEventListener('click', menuToggleClickHandler); diff --git a/routes/admin.js b/routes/admin.js index f2eb1ca..89d5bfc 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -2,8 +2,6 @@ const path = require('path'); const express = require('express'); -// no more using html pages, as we are using ejs engine -// const rootDir = require('../util/path'); const adminController = require('../controller/admin'); const routes = express.Router(); diff --git a/views/404.ejs b/views/404.ejs index 171cd1d..c258e04 100644 --- a/views/404.ejs +++ b/views/404.ejs @@ -1,7 +1,8 @@ -<%- include('./includes/head.ejs') %> +<%- include('includes/head.ejs') %> + -<%- include('./includes/navigation.ejs') %> + + <%- include('includes/navigation.ejs') %> +

    Page Not Found!

    -

    Page Not Found!

    - -<%- include('./includes/end.ejs') %> \ No newline at end of file +<%- include('includes/end.ejs') %> \ No newline at end of file diff --git a/views/admin/addProduct.ejs b/views/admin/add-product.ejs similarity index 83% rename from views/admin/addProduct.ejs rename to views/admin/add-product.ejs index aae0b8f..1b4e95e 100644 --- a/views/admin/addProduct.ejs +++ b/views/admin/add-product.ejs @@ -1,9 +1,11 @@ <%- include('../includes/head.ejs') %> - - -<%- include('../includes/navigation.ejs') %> + + + + <%- include('../includes/navigation.ejs') %> +
    @@ -11,20 +13,19 @@
    - +
    - +
    - +
    - <%- include('../includes/end.ejs') %> \ No newline at end of file diff --git a/views/admin/editProduct.ejs b/views/admin/edit-product.ejs similarity index 100% rename from views/admin/editProduct.ejs rename to views/admin/edit-product.ejs diff --git a/views/admin/products.ejs b/views/admin/products.ejs index 4eb161a..13827f6 100644 --- a/views/admin/products.ejs +++ b/views/admin/products.ejs @@ -1,35 +1,43 @@ - <%- include('../includes/head.ejs') %> - + + + + + <%- include('../includes/navigation.ejs') %> -<%- include('../includes/navigation.ejs') %> -
    - <% if (prods.length > 0) { %> -
    - <% for (let product of prods) { %> -
    -
    -

    <%= product.title %>

    -
    -
    - <%= product.title %> -
    -
    -

    $<%= product.price %>

    -

    <%= product.description %>

    -
    -
    - -
    - -
    -
    -
    - <% } %> -
    - <% } else { %> -

    No Products

    - <% } %> -
    +
    + <% if (prods.length > 0) { %> +
    + <% for (let product of prods) { %> +
    +
    +

    + <%= product.title %> +

    +
    +
    + <%= product.title %> +
    +
    +

    $ + <%= product.price %> +

    +

    + <%= product.description %> +

    +
    +
    + Edit +
    + +
    -<%- include('../includes/end.ejs') %> +
    +
    + <% } %> +
    + <% } else { %> +

    No Products Found!

    + <% } %> +
    + <%- include('../includes/end.ejs') %> \ No newline at end of file diff --git a/views/includes/end.ejs b/views/includes/end.ejs index 9870926..7cbf3b0 100644 --- a/views/includes/end.ejs +++ b/views/includes/end.ejs @@ -1,3 +1,4 @@ + \ No newline at end of file diff --git a/views/includes/navigation.ejs b/views/includes/navigation.ejs index ebd3a8e..974ac6d 100644 --- a/views/includes/navigation.ejs +++ b/views/includes/navigation.ejs @@ -1,15 +1,53 @@ - - - -
    +
    +
    + -
    \ No newline at end of file +
    + + \ No newline at end of file diff --git a/views/shop/cart.ejs b/views/shop/cart.ejs index 555a9a3..aac0373 100644 --- a/views/shop/cart.ejs +++ b/views/shop/cart.ejs @@ -1,7 +1,6 @@ <%- include('../includes/head.ejs') %> + -<%- include('../includes/navigation.ejs') %> - -

    Cart

    - -<%- include('../includes/end.ejs') %> \ No newline at end of file + + <%- include('../includes/navigation.ejs') %> + <%- include('../includes/end.ejs') %> \ No newline at end of file diff --git a/views/shop/index.ejs b/views/shop/index.ejs index a0f4d13..d882d8d 100644 --- a/views/shop/index.ejs +++ b/views/shop/index.ejs @@ -1,32 +1,34 @@ - <%- include('../includes/head.ejs') %> - + + -<%- include('../includes/navigation.ejs') %> -
    - <% if (prods.length > 0) { %> -
    - <% for (let product of prods) { %> -
    -
    -

    <%= product.title %>

    -
    -
    - <%= product.title %> -
    -
    -

    $<%= product.price %>

    -

    <%= product.description %>

    -
    -
    - -
    -
    - <% } %> -
    - <% } else { %> -

    No Products

    - <% } %> -
    + + <%- include('../includes/navigation.ejs') %> -<%- include('../includes/end.ejs') %> +
    + <% if (prods.length > 0) { %> +
    + <% for (let product of prods) { %> +
    +
    +

    <%= product.title %>

    +
    +
    + <%= product.title %> +
    +
    +

    $<%= product.price %>

    +

    <%= product.description %>

    +
    +
    + +
    +
    + <% } %> +
    + <% } else { %> +

    No Products Found!

    + <% } %> +
    +<%- include('../includes/end.ejs') %> \ No newline at end of file diff --git a/views/shop/orders.ejs b/views/shop/orders.ejs index 10a9d59..825bc2d 100644 --- a/views/shop/orders.ejs +++ b/views/shop/orders.ejs @@ -1,7 +1,9 @@ <%- include('../includes/head.ejs') %> + -<%- include('../includes/navigation.ejs') %> - -

    Your Orders

    - -<%- include('../includes/end.ejs') %> \ No newline at end of file + + <%- include('../includes/navigation.ejs') %> +
    +

    Nothing there!

    +
    + <%- include('../includes/end.ejs') %> \ No newline at end of file diff --git a/views/shop/productDetail.ejs b/views/shop/product-detail.ejs similarity index 100% rename from views/shop/productDetail.ejs rename to views/shop/product-detail.ejs diff --git a/views/shop/product-list.ejs b/views/shop/product-list.ejs new file mode 100644 index 0000000..da681e7 --- /dev/null +++ b/views/shop/product-list.ejs @@ -0,0 +1,41 @@ +<%- include('../includes/head.ejs') %> + + + + + <%- include('../includes/navigation.ejs') %> + +
    + <% if (prods.length > 0) { %> +
    + <% for (let product of prods) { %> +
    +
    +

    + <%= product.title %> +

    +
    +
    + <%= product.title %> +
    +
    +

    $ + <%= product.price %> +

    +

    + <%= product.description %> +

    +
    +
    +
    + +
    +
    +
    + <% } %> +
    + <% } else { %> +

    No Products Found!

    + <% } %> +
    + <%- include('../includes/end.ejs') %> \ No newline at end of file diff --git a/views/shop/productList.ejs b/views/shop/productList.ejs deleted file mode 100644 index 3b083a9..0000000 --- a/views/shop/productList.ejs +++ /dev/null @@ -1,34 +0,0 @@ - -<%- include('../includes/head.ejs') %> - - -<%- include('../includes/navigation.ejs') %> -
    - <% if (prods.length > 0) { %> -
    - <% for (let product of prods) { %> -
    -
    -

    <%= product.title %>

    -
    -
    - <%= product.title %> -
    -
    -

    $<%= product.price %>

    -

    <%= product.description %>

    -
    -
    -
    - -
    -
    -
    - <% } %> -
    - <% } else { %> -

    No Products

    - <% } %> -
    - -<%- include('../includes/end.ejs') %> From 86b1c0f838ba956ca05aaffd33a25727d1c7a0b7 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 20:02:34 +0530 Subject: [PATCH 16/50] 115 Extracting Dynamic Params --- controller/admin.js | 8 +++++++- controller/shop.js | 10 ++++++++++ data/products.json | 2 +- model/product.js | 5 ++++- routes/shop.js | 8 ++++++++ views/shop/product-list.ejs | 1 + 6 files changed, 31 insertions(+), 3 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index 4a95b4e..50eae80 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -7,13 +7,19 @@ exports.getAddProduct = (req, res, next) => { }); }; +// creating variable, which can store a number +let numID = 0; + exports.postAddProduct = (req, res, next) => { const title = req.body.title; const imageUrl = req.body.imageUrl; const description = req.body.description; const price = req.body.price; + // numID will be incremented by one, whenever new product will be added + numID = numID + 1; - const product = new Product(title, imageUrl, description, price); + const product = new Product(title, imageUrl, description, price,numID); + product.save(); res.redirect("/"); }; diff --git a/controller/shop.js b/controller/shop.js index 22f81f9..813975e 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -10,6 +10,16 @@ exports.getProduct = (req, res, next) => { }) }; +exports.getDetails = (req, res, next) => { + // we can access productID because of "params" object which express gives on the request + // "productID" is same give in "routes" folder of "shop". both the same should be same, to access that property + const productId = req.params.productID; + console.log(productId); + // redirecting the result + res.redirect('/'); + // we not only store the productID, but we can use it to do other work +}; + exports.getCart = (req, res, next) => { res.render('shop/cart', { pageTitle : 'Cart', diff --git a/data/products.json b/data/products.json index 52b3322..d7e1f1e 100644 --- a/data/products.json +++ b/data/products.json @@ -1 +1 @@ -[{"title":"book","imageUrl":"","description":"sdfgh","price":".01"}] \ No newline at end of file +[{"title":"s","imageUrl":"","description":"","price":"","id":1}] \ No newline at end of file diff --git a/model/product.js b/model/product.js index 6c443fe..a8b54a8 100644 --- a/model/product.js +++ b/model/product.js @@ -18,14 +18,17 @@ const getProductsFromFile = (cb) => { module.exports = class Product { - constructor(title, imageUrl, description, price) { + constructor(title, imageUrl, description, price,numID) { this.title = title; this.imageUrl = imageUrl; this.description = description; this.price = price; + // storing product id, whichis passed to constructor + this.id = numID; } save() { + getProductsFromFile((products) => { products.push(this); diff --git a/routes/shop.js b/routes/shop.js index ea1efba..621c6da 100644 --- a/routes/shop.js +++ b/routes/shop.js @@ -10,6 +10,14 @@ routes.get('/', shopController.getIndex); routes.get('/products', shopController.getProduct); +// if we have one more url as "/products/delete", then it should be above than "/products/:productID". if it is down, it will never reach this url as "/products/:productID" will get executed. +// eg: +// routes.get('/products/delete', shopController.getDetails); + +// using the dynamic params in the url +// because of ":", now url wil be treated as "/products/1" or "/products/abcd" or anything. Instead of fixed url ie, "/products/:productID" +routes.get('/products/:productId', shopController.getDetails); + routes.get('/cart', shopController.getCart); routes.get('/orders', shopController.getOrders); diff --git a/views/shop/product-list.ejs b/views/shop/product-list.ejs index da681e7..4a3a543 100644 --- a/views/shop/product-list.ejs +++ b/views/shop/product-list.ejs @@ -27,6 +27,7 @@

    + Details
    From 66c11fc4bd89eb5c75a056dad0e2550dc8a66f09 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 22:17:26 +0530 Subject: [PATCH 17/50] 116 Loading Product Detail Data --- controller/admin.js | 7 ++++--- controller/shop.js | 12 ++++++------ data/products.json | 2 +- model/product.js | 39 ++++++++++++++++++++++++++------------- 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index 50eae80..351a947 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -8,17 +8,18 @@ exports.getAddProduct = (req, res, next) => { }; // creating variable, which can store a number -let numID = 0; +// let numID = 0; exports.postAddProduct = (req, res, next) => { + // let numID = Math.random(); const title = req.body.title; const imageUrl = req.body.imageUrl; const description = req.body.description; const price = req.body.price; // numID will be incremented by one, whenever new product will be added - numID = numID + 1; + // numID = numID + 1; - const product = new Product(title, imageUrl, description, price,numID); + const product = new Product(title, imageUrl, description, price); product.save(); res.redirect("/"); diff --git a/controller/shop.js b/controller/shop.js index 813975e..a405a64 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -11,13 +11,13 @@ exports.getProduct = (req, res, next) => { }; exports.getDetails = (req, res, next) => { - // we can access productID because of "params" object which express gives on the request - // "productID" is same give in "routes" folder of "shop". both the same should be same, to access that property - const productId = req.params.productID; - console.log(productId); - // redirecting the result + const productID = req.params.productId; + console.log(productID); + Product.findById(productID, pro => { + console.log(pro); + }); res.redirect('/'); - // we not only store the productID, but we can use it to do other work + }; exports.getCart = (req, res, next) => { diff --git a/data/products.json b/data/products.json index d7e1f1e..011ef7f 100644 --- a/data/products.json +++ b/data/products.json @@ -1 +1 @@ -[{"title":"s","imageUrl":"","description":"","price":"","id":1}] \ No newline at end of file +[{"title":"wer","imageUrl":"asdf","description":"ertfygh","price":"54","id":"1.1949186432461922"},{"title":"wefr","imageUrl":"desf","description":"4et5y","price":"3521","id":"2"},{"title":"asdfg","imageUrl":"asdf","description":"","price":"65","id":"1.6094309610182131"},{"title":"sdfg","imageUrl":"sd","description":"","price":"5823","id":"0.3689965042774357"}] \ No newline at end of file diff --git a/model/product.js b/model/product.js index a8b54a8..a317c55 100644 --- a/model/product.js +++ b/model/product.js @@ -5,40 +5,53 @@ const rootDir = require('../util/path'); const p = path.join(rootDir, 'data', 'products.json'); -const getProductsFromFile = (cb) => { +const getProductsFromFile = cb => { fs.readFile(p, (err, fileContent) => { if(err) { - return cb([]); - } - return cb(JSON.parse(fileContent)); - + cb([]); + } else { + cb(JSON.parse(fileContent)); + } }); } module.exports = class Product { - constructor(title, imageUrl, description, price,numID) { + constructor(title, imageUrl, description, price) { this.title = title; this.imageUrl = imageUrl; this.description = description; this.price = price; - // storing product id, whichis passed to constructor - this.id = numID; + // storing product id, which is passed to constructor + // converting the number to string format + // this.id = numID.toString(); } save() { - + // easy way to define a id to the every new product we are stronging in an array + this.id = Math.random().toString(); getProductsFromFile((products) => { products.push(this); fs.writeFile(p, JSON.stringify(products), (err) => { console.log(err); }); - }) - } + }); + }; static fetchAll(cb) { getProductsFromFile(cb); - } -} \ No newline at end of file + }; + + static findById(id, cb) { + getProductsFromFile(prod => { + // thus, we will have array of objects and each object will have an id + // "find" method will recieve a function, which will get an product which it currently looking at and then check its id with id we passed. if id got matched, that product is retured + const ppp = prod.find(p => p.id === id); + console.log(ppp); + // thus, afterwards calling a callback with that product(from above statement) + cb(ppp); + }); + }; +}; \ No newline at end of file From 8b718a72543e188ae5b9f439c69aa4694761c96b Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 22:35:37 +0530 Subject: [PATCH 18/50] 117 Rendering the Product Detail View --- controller/shop.js | 14 +++++++------- data/products.json | 2 +- model/product.js | 8 ++++---- public/css/main.css | 4 ++++ views/shop/product-detail.ejs | 21 +++++++++++++++++++++ 5 files changed, 37 insertions(+), 12 deletions(-) diff --git a/controller/shop.js b/controller/shop.js index a405a64..fcd5e08 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -13,24 +13,24 @@ exports.getProduct = (req, res, next) => { exports.getDetails = (req, res, next) => { const productID = req.params.productId; console.log(productID); - Product.findById(productID, pro => { - console.log(pro); + Product.findById(productID, product => { + // console.log(product); + res.render('shop/product-detail', { pageTitle: product.title, product: product, path: '/products' }); }); - res.redirect('/'); }; exports.getCart = (req, res, next) => { res.render('shop/cart', { - pageTitle : 'Cart', - path : '/cart' + pageTitle: 'Cart', + path: '/cart' }); }; exports.getOrders = (req, res, next) => { res.render('shop/orders', { - pageTitle : 'Orders', - path : '/orders' + pageTitle: 'Orders', + path: '/orders' }); }; diff --git a/data/products.json b/data/products.json index 011ef7f..55dffd7 100644 --- a/data/products.json +++ b/data/products.json @@ -1 +1 @@ -[{"title":"wer","imageUrl":"asdf","description":"ertfygh","price":"54","id":"1.1949186432461922"},{"title":"wefr","imageUrl":"desf","description":"4et5y","price":"3521","id":"2"},{"title":"asdfg","imageUrl":"asdf","description":"","price":"65","id":"1.6094309610182131"},{"title":"sdfg","imageUrl":"sd","description":"","price":"5823","id":"0.3689965042774357"}] \ No newline at end of file +[{"title":"wer","imageUrl":"asdf","description":"ertfygh","price":"54","id":"1.1949186432461922"},{"title":"wefr","imageUrl":"desf","description":"4et5y","price":"3521","id":"2"},{"title":"asdfg","imageUrl":"asdf","description":"","price":"65","id":"1.6094309610182131"},{"title":"sdfg","imageUrl":"sd","description":"","price":"5823","id":"0.3689965042774357"},{"title":"sdg","imageUrl":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8QDxIPDxAQEA8PDQ0PDw8PDw8PEBAPFREWFhUVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGC8iHSUtLSsrLS0rLS0rMC4rLTAtLS0rLSstLS0tLS0rLS0tLzUtLS0tLSstLS0tLS0tLS0rK//AABEIALcBEwMBIgACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAADBAACAQUGB//EAEkQAAIBAgIFBgoGCAYBBQAAAAECAAMRBCEFEjFBUQYTYXGBkQciMlKSobHB0fBCVHKT0uEWFyNDYoKj8RREU2Oy4lUVM0Vzg//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/EACgRAQACAQQBBAIBBQAAAAAAAAABAhEDEyFREjFBUmEUkQQiMkKBof/aAAwDAQACEQMRAD8A8vUQirIohVWBFWECyKsKqwMKsIqyyrCKsCqrCqksqQirAqqy4WXVYRUgUCS4SEVIQJAEElgkKElwkAISZCQ4SWCQF9SZ1IxqSakBbUk1IzqSakBXUmCkZ1JgpAVKShSNlJQpAUKShWNlIMpAUKyjLGmSDZYCrJBssaZYNlgKssEyxplg2WAqywTLGmWCZYC+rJCFZmBFWEVZFWFVYEVYVVmVWFVYGFWFVZlVhVWBhVhVSWRIVVgVVIRUl1SEVIFFSXCQqpCKkAQSXFOGCS4SAAU5YJGAksEgLakzqRnm5nm4CupMaka5uTm4ChSVKRwpKlICRpyhSOlINkgJMkoyRxkg2SAmywTJHGSCZICbLBsscZIFkgKMsEyxtlgmWAoywTLGmWCZYC1pIUrJAirCqswohkWBlFhVWRVhkWBFWGRZEWGVYGFWGVZlVhkSBVUhlSWVIZUgUVIRUnUaD0ErUi9UZ1B4o4Lxmv0loh6LcU3N8YyNWqQgpwqpCBIAAksKcOElwkBfm","description":"dfgnvh","price":"582","id":"0.49634733614067117"},{"title":"asdf","imageUrl":"data:image/jpeg;base64,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","description":"asdfgb","price":"6352","id":"0.4961980477018628"}] \ No newline at end of file diff --git a/model/product.js b/model/product.js index a317c55..284b992 100644 --- a/model/product.js +++ b/model/product.js @@ -45,13 +45,13 @@ module.exports = class Product { }; static findById(id, cb) { - getProductsFromFile(prod => { + getProductsFromFile(products => { // thus, we will have array of objects and each object will have an id // "find" method will recieve a function, which will get an product which it currently looking at and then check its id with id we passed. if id got matched, that product is retured - const ppp = prod.find(p => p.id === id); - console.log(ppp); + const product = products.find(p => p.id === id); + // console.log(product); // thus, afterwards calling a callback with that product(from above statement) - cb(ppp); + cb(product); }); }; }; \ No newline at end of file diff --git a/public/css/main.css b/public/css/main.css index 3e3e103..5687205 100644 --- a/public/css/main.css +++ b/public/css/main.css @@ -193,6 +193,10 @@ form { color: white; } +.centered { + text-align: center; +} + @media (min-width: 768px) { .main-header__nav { display: flex; diff --git a/views/shop/product-detail.ejs b/views/shop/product-detail.ejs index e69de29..2063e3f 100644 --- a/views/shop/product-detail.ejs +++ b/views/shop/product-detail.ejs @@ -0,0 +1,21 @@ +<%- include('../includes/head.ejs') %> + + + <%- include('../includes/navigation.ejs') %> + +
    +

    <%= product.title %>

    +
    +
    + <%= product.title %> +
    +

    <%= product.price %>

    +

    <%= product.description %>

    + + +
    + +
    +
    + +<%- include('../includes/end.ejs') %> \ No newline at end of file From bbcaff1eafaff7a67a62a455bce1073ec8100fab Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Wed, 15 Jan 2020 23:33:07 +0530 Subject: [PATCH 19/50] 118 Passing Data with POST Requests --- controller/shop.js | 10 ++++++++-- model/product.js | 8 -------- routes/shop.js | 8 ++------ views/includes/add-to-cart.ejs | 4 ++++ views/shop/index.ejs | 5 ++--- views/shop/product-detail.ejs | 8 +++----- views/shop/product-list.ejs | 4 +--- 7 files changed, 20 insertions(+), 27 deletions(-) create mode 100644 views/includes/add-to-cart.ejs diff --git a/controller/shop.js b/controller/shop.js index fcd5e08..83adb62 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -12,9 +12,8 @@ exports.getProduct = (req, res, next) => { exports.getDetails = (req, res, next) => { const productID = req.params.productId; - console.log(productID); + // console.log(productID); Product.findById(productID, product => { - // console.log(product); res.render('shop/product-detail', { pageTitle: product.title, product: product, path: '/products' }); }); @@ -27,6 +26,13 @@ exports.getCart = (req, res, next) => { }); }; +exports.postCart = (req, res, next) => { + // as request was "POST", so it contains the productID as agrument within the url of "form" + // "productID" is the name given to the value ID, in the form field. + console.log(req.body.productID); + res.redirect('/'); +} + exports.getOrders = (req, res, next) => { res.render('shop/orders', { pageTitle: 'Orders', diff --git a/model/product.js b/model/product.js index 284b992..adb8ffa 100644 --- a/model/product.js +++ b/model/product.js @@ -23,13 +23,9 @@ module.exports = class Product { this.imageUrl = imageUrl; this.description = description; this.price = price; - // storing product id, which is passed to constructor - // converting the number to string format - // this.id = numID.toString(); } save() { - // easy way to define a id to the every new product we are stronging in an array this.id = Math.random().toString(); getProductsFromFile((products) => { products.push(this); @@ -46,11 +42,7 @@ module.exports = class Product { static findById(id, cb) { getProductsFromFile(products => { - // thus, we will have array of objects and each object will have an id - // "find" method will recieve a function, which will get an product which it currently looking at and then check its id with id we passed. if id got matched, that product is retured const product = products.find(p => p.id === id); - // console.log(product); - // thus, afterwards calling a callback with that product(from above statement) cb(product); }); }; diff --git a/routes/shop.js b/routes/shop.js index 621c6da..5da53da 100644 --- a/routes/shop.js +++ b/routes/shop.js @@ -10,16 +10,12 @@ routes.get('/', shopController.getIndex); routes.get('/products', shopController.getProduct); -// if we have one more url as "/products/delete", then it should be above than "/products/:productID". if it is down, it will never reach this url as "/products/:productID" will get executed. -// eg: -// routes.get('/products/delete', shopController.getDetails); - -// using the dynamic params in the url -// because of ":", now url wil be treated as "/products/1" or "/products/abcd" or anything. Instead of fixed url ie, "/products/:productID" routes.get('/products/:productId', shopController.getDetails); routes.get('/cart', shopController.getCart); +routes.post('/cart', shopController.postCart); + routes.get('/orders', shopController.getOrders); module.exports = routes; diff --git a/views/includes/add-to-cart.ejs b/views/includes/add-to-cart.ejs new file mode 100644 index 0000000..965e09c --- /dev/null +++ b/views/includes/add-to-cart.ejs @@ -0,0 +1,4 @@ +
    + + +
    \ No newline at end of file diff --git a/views/shop/index.ejs b/views/shop/index.ejs index d882d8d..770835f 100644 --- a/views/shop/index.ejs +++ b/views/shop/index.ejs @@ -21,9 +21,8 @@

    $<%= product.price %>

    <%= product.description %>

    -
    - -
    + + <%- include('../includes/add-to-cart.ejs', {product: product}) %> <% } %> diff --git a/views/shop/product-detail.ejs b/views/shop/product-detail.ejs index 2063e3f..dbea8f0 100644 --- a/views/shop/product-detail.ejs +++ b/views/shop/product-detail.ejs @@ -11,11 +11,9 @@

    <%= product.price %>

    <%= product.description %>

    - - -
    - -
    + + + <%- include('../includes/add-to-cart.ejs') %>
    <%- include('../includes/end.ejs') %> \ No newline at end of file diff --git a/views/shop/product-list.ejs b/views/shop/product-list.ejs index 4a3a543..22c5db8 100644 --- a/views/shop/product-list.ejs +++ b/views/shop/product-list.ejs @@ -28,9 +28,7 @@
    Details -
    - -
    + <%- include('../includes/add-to-cart.ejs', {product: product}) %>
    <% } %> From f17f710f539127081519481aa50e16915ec6658d Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Thu, 16 Jan 2020 20:51:42 +0530 Subject: [PATCH 20/50] 119 Adding a Cart Model --- controller/shop.js | 9 ++++-- data/cart.json | 1 + model/cart.js | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 data/cart.json create mode 100644 model/cart.js diff --git a/controller/shop.js b/controller/shop.js index 83adb62..2115113 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -1,4 +1,5 @@ -const Product = require("../model/product"); +const Product = require('../model/product'); +const Cart = require('../model/cart'); exports.getProduct = (req, res, next) => { Product.fetchAll((products) => { @@ -29,7 +30,11 @@ exports.getCart = (req, res, next) => { exports.postCart = (req, res, next) => { // as request was "POST", so it contains the productID as agrument within the url of "form" // "productID" is the name given to the value ID, in the form field. - console.log(req.body.productID); + const productID = req.body.productID + console.log(productID); + Product.findById(productID, product => { + Cart.addProduct(productID, product.price); + }) res.redirect('/'); } diff --git a/data/cart.json b/data/cart.json new file mode 100644 index 0000000..4d88914 --- /dev/null +++ b/data/cart.json @@ -0,0 +1 @@ +{"products":[{"id":"0.4961980477018628","qty":7},{"id":"0.49634733614067117","qty":1}],"totalPrice":45046} \ No newline at end of file diff --git a/model/cart.js b/model/cart.js new file mode 100644 index 0000000..f300c46 --- /dev/null +++ b/model/cart.js @@ -0,0 +1,77 @@ +// our basic idea is to cart to hold all the objects we add and we want to group products by id and increade there quantity in case when we add producy more than once. + +// module.exports = class Cart{ +// constructor() { +// this.product = [], +// this.totalPrice = 0; +// } + +// // we to cart to add or remove products. but the problem we have is that cart itself is not a object, we will constently recreate. not for every new product that we add, we dont want to have a new cart, instaed there will be. +// // there will be always a cart in our app, we need to manage it +// } +const fs = require('fs'); +const path = require('path'); + +const rootDir = require('../util/path'); + +const p = path.join(rootDir, 'data', 'cart.json'); + +module.exports = class Cart { + static addProduct(id, productPrice) { + // fetch the previous product + fs.readFile(p, (err, fileContent) => { + let cart = {products: [], totalPrice: 0}; + if(!err) { + cart = JSON.parse(fileContent); + } + // we will get all the products which are in cart + // console.log('cart : ' ,cart); + + // // analysing the cart => finding existing product + // const exisitingProduct = cart.products.find(prod => prod.id === id); + // let updatedProduct; + + // // add new product / incraese the quantity + // if(exisitingProduct) { + // updatedProduct = {...exisitingProduct}; + // updatedProduct.qty = updatedProduct.qty + 1; + // // here also, we have to update the product in the cart. as product is already present here, we need to find the index where it is located + // } else { + // updatedProduct = {id: id, qty: 1}; + // // updating the cart after adding new product to the cart + // cart.products = [...cart.products, updatedProduct]; + // } + + // cart.totalPrice = cart.totalPrice + productPrice; + + + // analysing the cart => finding existing product + const exisitingProductIndex = cart.products.findIndex(prod => prod.id === id); + const exisitingProduct = cart.products[exisitingProductIndex]; + let updatedProduct; + + // add new product / incraese the quantity + if(exisitingProduct) { + updatedProduct = {...exisitingProduct}; + updatedProduct.qty = updatedProduct.qty + 1; + // here also, we have to update the product in the cart. as product is already present here, we need to find the index where it is located + cart.products = [...cart.products]; + cart.products[exisitingProductIndex] = updatedProduct; + } else { + updatedProduct = {id: id, qty: 1}; + // updating the cart after adding new product to the cart + cart.products = [...cart.products, updatedProduct]; + } + + // productPrice is acting as a string here, to convert into number type, we are adding "+" operator before varible name + cart.totalPrice = cart.totalPrice + +productPrice; + + // writeing down the changes to file + fs.writeFile(p, JSON.stringify(cart), err => { + console.log(err); + }); + + }); + + } +} \ No newline at end of file From 44051ecf9d9256f836e06330b2afb2d08a60f81f Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Thu, 16 Jan 2020 21:38:22 +0530 Subject: [PATCH 21/50] 120 Using Query Params --- controller/admin.js | 39 +++++++++++++++++++++++++++++------- routes/admin.js | 2 ++ views/admin/add-product.ejs | 31 ---------------------------- views/admin/edit-product.ejs | 31 ++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 38 deletions(-) delete mode 100644 views/admin/add-product.ejs diff --git a/controller/admin.js b/controller/admin.js index 351a947..0f766bc 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -1,23 +1,17 @@ const Product = require("../model/product"); exports.getAddProduct = (req, res, next) => { - res.render("admin/add-product", { + res.render("admin/edit-product", { path: "/admin/add-product", pageTitle: "Add Products", }); }; -// creating variable, which can store a number -// let numID = 0; - exports.postAddProduct = (req, res, next) => { - // let numID = Math.random(); const title = req.body.title; const imageUrl = req.body.imageUrl; const description = req.body.description; const price = req.body.price; - // numID will be incremented by one, whenever new product will be added - // numID = numID + 1; const product = new Product(title, imageUrl, description, price); @@ -25,6 +19,37 @@ exports.postAddProduct = (req, res, next) => { res.redirect("/"); }; +exports.getEditProduct = (req, res, next) => { + // now lets say, we need to get additional confirmation by ensuring that people have to pass us so called "query parameters"in a url. + // a query parameter can be added to any url by adding a question mark and then a key,value pair seprated by equal to sign(keyValue = valueValue) + // in our case, Eg: http://localhost:3000/admin/edit-product/12?edit=true + // and we can have multiple query parameters by seprating them with ampersand sign(&) + // Eg: http://localhost:3000/admin/edit-product/12?edit=true&title=new + // this "edit=true&title=new" is called as optinal data. this data is not to be in routes file, where we determine route for different files + // but, we can check for query paramerters in our controllers + // this is done by:- + + // "query" is inbuild propertly given by express + // here we are checking key "edit" if it is passed in optianl data + // so if "edit" value is set somewhere in query parameters, we will get response as "true" + // the extrated value (ie, response) is always a string. so it will be "true" not true(bool value) + // if it didnt get the key "edit", it will set to undefined that is false + const editMode = req.query.edit + // thus, now we will enter edit mode, only if it editMode is set, which we have done + + if(!editMode) { + // well, it is redundant thing here. as we already know we are editing new product here + res.redirect('/'); + } + + // so query parameters are used to tracking down users or some filters set on the page + res.render("admin/edit-product", { + path: "/admin/edit-product", + pageTitle: "Edit Products", + editing: editMode + }); +}; + exports.getProducts = (req, res, next) => { Product.fetchAll((products) => { res.render("admin/products", { diff --git a/routes/admin.js b/routes/admin.js index 89d5bfc..70a4bec 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -10,5 +10,7 @@ routes.get('/add-product', adminController.getAddProduct); routes.post('/add-product', adminController.postAddProduct); +routes.get('/edit-product/:productID', adminController.getEditProduct); + routes.get('/products',adminController.getProducts) module.exports = routes; diff --git a/views/admin/add-product.ejs b/views/admin/add-product.ejs deleted file mode 100644 index 1b4e95e..0000000 --- a/views/admin/add-product.ejs +++ /dev/null @@ -1,31 +0,0 @@ -<%- include('../includes/head.ejs') %> - - - - - - <%- include('../includes/navigation.ejs') %> - -
    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    - - -
    -
    -<%- include('../includes/end.ejs') %> \ No newline at end of file diff --git a/views/admin/edit-product.ejs b/views/admin/edit-product.ejs index e69de29..1b4e95e 100644 --- a/views/admin/edit-product.ejs +++ b/views/admin/edit-product.ejs @@ -0,0 +1,31 @@ +<%- include('../includes/head.ejs') %> + + + + + + <%- include('../includes/navigation.ejs') %> + +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    + + +
    +
    +<%- include('../includes/end.ejs') %> \ No newline at end of file From 7efdd0fcaf24cf948ef9862cee76beb81ec5aebb Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Thu, 16 Jan 2020 22:46:57 +0530 Subject: [PATCH 22/50] 121 Pre-Populating the Edit Product Page with Data --- controller/admin.js | 35 +++++++++++----------------- data/products.json | 45 +++++++++++++++++++++++++++++++++++- views/admin/edit-product.ejs | 22 +++++++++++++----- 3 files changed, 73 insertions(+), 29 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index 0f766bc..349fbb4 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -4,6 +4,7 @@ exports.getAddProduct = (req, res, next) => { res.render("admin/edit-product", { path: "/admin/add-product", pageTitle: "Add Products", + editing: false }); }; @@ -20,34 +21,24 @@ exports.postAddProduct = (req, res, next) => { }; exports.getEditProduct = (req, res, next) => { - // now lets say, we need to get additional confirmation by ensuring that people have to pass us so called "query parameters"in a url. - // a query parameter can be added to any url by adding a question mark and then a key,value pair seprated by equal to sign(keyValue = valueValue) - // in our case, Eg: http://localhost:3000/admin/edit-product/12?edit=true - // and we can have multiple query parameters by seprating them with ampersand sign(&) - // Eg: http://localhost:3000/admin/edit-product/12?edit=true&title=new - // this "edit=true&title=new" is called as optinal data. this data is not to be in routes file, where we determine route for different files - // but, we can check for query paramerters in our controllers - // this is done by:- - - // "query" is inbuild propertly given by express - // here we are checking key "edit" if it is passed in optianl data - // so if "edit" value is set somewhere in query parameters, we will get response as "true" - // the extrated value (ie, response) is always a string. so it will be "true" not true(bool value) - // if it didnt get the key "edit", it will set to undefined that is false const editMode = req.query.edit - // thus, now we will enter edit mode, only if it editMode is set, which we have done - if(!editMode) { - // well, it is redundant thing here. as we already know we are editing new product here res.redirect('/'); } - // so query parameters are used to tracking down users or some filters set on the page - res.render("admin/edit-product", { - path: "/admin/edit-product", - pageTitle: "Edit Products", - editing: editMode + // taking out productID from the dynamic parameters which we are passing in url + const productID = req.params.productID; + // console.log(productID); + + Product.findById(productID, product => { + res.render("admin/edit-product", { + path: "/admin/edit-product", + pageTitle: "Edit Products", + editing: editMode, + product: product + }); }); + }; exports.getProducts = (req, res, next) => { diff --git a/data/products.json b/data/products.json index 55dffd7..d845810 100644 --- a/data/products.json +++ b/data/products.json @@ -1 +1,44 @@ -[{"title":"wer","imageUrl":"asdf","description":"ertfygh","price":"54","id":"1.1949186432461922"},{"title":"wefr","imageUrl":"desf","description":"4et5y","price":"3521","id":"2"},{"title":"asdfg","imageUrl":"asdf","description":"","price":"65","id":"1.6094309610182131"},{"title":"sdfg","imageUrl":"sd","description":"","price":"5823","id":"0.3689965042774357"},{"title":"sdg","imageUrl":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8QDxIPDxAQEA8PDQ0PDw8PDw8PEBAPFREWFhUVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGC8iHSUtLSsrLS0rLS0rMC4rLTAtLS0rLSstLS0tLS0rLS0tLzUtLS0tLSstLS0tLS0tLS0rK//AABEIALcBEwMBIgACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAADBAACAQUGB//EAEkQAAIBAgIFBgoGCAYBBQAAAAECAAMRBCEFEjFBUQYTYXGBkQciMlKSobHB0fBCVHKT0uEWFyNDYoKj8RREU2Oy4lUVM0Vzg//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/EACgRAQACAQQBBAIBBQAAAAAAAAABAhEDEyFREjFBUmEUkQQiMkKBof/aAAwDAQACEQMRAD8A8vUQirIohVWBFWECyKsKqwMKsIqyyrCKsCqrCqksqQirAqqy4WXVYRUgUCS4SEVIQJAEElgkKElwkAISZCQ4SWCQF9SZ1IxqSakBbUk1IzqSakBXUmCkZ1JgpAVKShSNlJQpAUKShWNlIMpAUKyjLGmSDZYCrJBssaZYNlgKssEyxplg2WAqywTLGmWCZYC+rJCFZmBFWEVZFWFVYEVYVVmVWFVYGFWFVZlVhVWBhVhVSWRIVVgVVIRUl1SEVIFFSXCQqpCKkAQSXFOGCS4SAAU5YJGAksEgLakzqRnm5nm4CupMaka5uTm4ChSVKRwpKlICRpyhSOlINkgJMkoyRxkg2SAmywTJHGSCZICbLBsscZIFkgKMsEyxtlgmWAoywTLGmWCZYC1pIUrJAirCqswohkWBlFhVWRVhkWBFWGRZEWGVYGFWGVZlVhkSBVUhlSWVIZUgUVIRUnUaD0ErUi9UZ1B4o4Lxmv0loh6LcU3N8YyNWqQgpwqpCBIAAksKcOElwkBfm","description":"dfgnvh","price":"582","id":"0.49634733614067117"},{"title":"asdf","imageUrl":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8QDxIPDxAQEA8PDQ0PDw8PDw8PEBAPFREWFhUVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGC8iHSUtLSsrLS0rLS0rMC4rLTAtLS0rLSstLS0tLS0rLS0tLzUtLS0tLSstLS0tLS0tLS0rK//AABEIALcBEwMBIgACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAADBAACAQUGB//EAEkQAAIBAgIFBgoGCAYBBQAAAAECAAMRBCEFEjFBUQYTYXGBkQciMlKSobHB0fBCVHKT0uEWFyNDYoKj8RREU2Oy4lUVM0Vzg//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/EACgRAQACAQQBBAIBBQAAAAAAAAABAhEDEyFREjFBUmEUkQQiMkKBof/aAAwDAQACEQMRAD8A8vUQirIohVWBFWECyKsKqwMKsIqyyrCKsCqrCqksqQirAqqy4WXVYRUgUCS4SEVIQJAEElgkKElwkAISZCQ4SWCQF9SZ1IxqSakBbUk1IzqSakBXUmCkZ1JgpAVKShSNlJQpAUKShWNlIMpAUKyjLGmSDZYCrJBssaZYNlgKssEyxplg2WAqywTLGmWCZYC+rJCFZmBFWEVZFWFVYEVYVVmVWFVYGFWFVZlVhVWBhVhVSWRIVVgVVIRUl1SEVIFFSXCQqpCKkAQSXFOGCS4SAAU5YJGAksEgLakzqRnm5nm4CupMaka5uTm4ChSVKRwpKlICRpyhSOlINkgJMkoyRxkg2SAmywTJHGSCZICbLBsscZIFkgKMsEyxtlgmWAoywTLGmWCZYC1pIUrJAirCqswohkWBlFhVWRVhkWBFWGRZEWGVYGFWGVZlVhkSBVUhlSWVIZUgUVIRUnUaD0ErUi9UZ1B4o4Lxmv0loh6LcU3N8YyNWqQgpwqpCBIAAksKcOElwkBfm5ObjOpM6kBXm5Cka1JjUgKGnKlI4UlCkBMpBskdKQbJASZIJkjzJBMkBFkgmSOskE6QEWWCZY46QLLATdYFljjrAusBR1gWWNusC6wFtWSE1ZmBVRDosogh0ECyrDIsqiw6LAsiwyLMIsOiwMokMiSIsOiQIiTccn9F8/VzH7NLM548F7fdE8HhWqOqILsxsJ6DozALQpCmuZGbN5zHaYBQlsoDEUww1SLjeI42UXZe2TCuZ0hogr41PNd67xNeEnaFZrcdo5W8ZRZuG4wjQBJYU4waRBsRmJkJKF+bmebjISTUgLc3MGnGtSTUgKGnKFI4UlSkBJkg2SOskNhtHs/QvGBq6WGZzqqLmF0pos0QpJvrXv0GdZgMKlMWUZ8d8rpvCc5QYfSUa69Y/K8mVcCyQLpHmSBdJUIusA6R50gHWAi6wLrHHWAdYCbrAusbdYB1gLFZIQiSBVBDoJRBDosC6LDosogjCLAsixhFlUWMIsCyLDosqizY6KwjVaqIu9gTlcBRmSYHS8ltF82nPOPHceKD9FPiZ0FphCNky97ZSwAVDnnlnYbfZ7x27JRWB/t1QrL7Nmz1fO2U5vhtzy4G27o/OFVtBssKDllsy2X4ZDp+eMwyyDW4vDBs/pe2a/Um+qrEsTQ3jbINfqzOrDakzqSoBqzGrGNSQpAWKTHN3yEdp4Yt0DjHKGGC7NvGAlhtHja+fRNilLcBCrT3nZCWy4C3zeRQ1UDp49EKVlBnkMhuPHLd22hkGUuByentGhBrKLAH1HZ8JoHSehaQw4dCp+kCPhOFrUipKnIgkEdIkgIOkXdY86xd1lQjUWLusedYvUWAk6wDrG3WAcQFbSQhWSBRBDoIOmIwggEQRimsEgjNNYBUWMIsHTEYprALSS+W8zt9A6NFFNYj9o6i54DbaaHk3o/nKmuR4lPM9LbhOyJklYDrPYX9xPslcNj1J1WyuSFJIz+ffAYh77xwFs2E19Ubd195zPbOc3w1jLoWThsgynC3rHrmlwulmpmzXZOnyh0ze0aiVAHQ3Hztm6Xi3ozMTChS/Xnnlfjn8RBbP7kjYeiHZbStgfy93CbQBlgqiw7A7877+3ZaUYXmZUg6ZzGrD1ltJqxCAakPSw+890vSpxlE+eMKqqQir87pbs7L59smqT0WAyA7+rdLhGD3n537pnUzuTwsNo+cv7y6oNgG83y+c4QL35bZQIJxyGVhJWqqguxAEV0hpRKWQ8Z9w3DrM0Zq1KrazEm+zcoHQJx1NeteI5luKTLcLiecN9g3CaTlDhLOKg2OLH7Q/KbOgAguxA+dwimlsVr0yqjxbgknb2RS0z6loc06xeosedYtUWdWCNRYvUWO1Fi1QQEqixZxHagiziAsVmIQiSAKmIwggUEYQQD0xGaYgKYjVMQDUxGaYgaYm10RgjVqKLeJe7HoG34dsDqNCXp4dAQBca1gLbdl+mMVsfSHiu2rfje3fumKrTQY6oSSTv2DiOqcbXw6RDfAI/kOp6iIvXwreszka175EhrnMHMZ/O2SjpPEpktV+gMdb2zjOpHvDWHQVsOw7uv2wWHxNSg2svap2N1zXJynrjy0puBtJBUxqnyjw7ZVKb0zxHjj1Zznx6xKutwGkKdcZZMNqnaIdqc5ajzdTx8PVRmGd1azDrE3GC0kTZKw1W2Btx656dPXzxdi1OjpAtY/C+7b74Jltl6/yjTLv3WgGXd3T0S5l6yZdUGNwjDDKBw2ec55xw1gxTSXJtx6+nok+HXLIntvNwigS/XcdIv0Q6px7pYCw9pM1mK0tYlaQ123t9EfGZvqVpGbSsRM+jYYmulNdaowVemaHG6XqVfEogouzXPlHqG6anSemMPTa9etzlQfQTx2HYMlnPY7lVVe60FFBfOPjVPgJ5L6178RxH/XSKxDpqopURrVnAJzsTdj2RCpyivlRXUHnuASd2WfzacgFZm12Ys227azHtmxwyWyvl0g7e6ZpWIJl0mDrl82YsdtzNkq3FjvmkwCEMCOo57pu6U9EMtRXp2JHA2itRZt9JUtjccj1zWVBO7mSqLFagj1QRWoICVQRWoI7UEVqCAsRMS5EkANOMUxNgnJ3Efw+lDJoCv/AA98BOmIzTEbTQdbgvfDpoetwHfAXp7ukgDrM7bRWHWlTFyASN5tOX0bo5mxSq3k0gHbeNY5KPfNzpLFHW1beTsABM4a2p4ulatrWAOx17xEamAvtcdrCal8Qd4I62VYE1VP0b9tR55Z1pn2dfCGxfRlEeVVQdbQTYLC766d94mGG6kvaqj2mFUvuRB3e5ZnynpfGBTgcKf3yeuDfQ1FhZatM/zWmb1OKDv+Ex45+lS7f7SZ+jBZ+Tj7UIuNjI2YhKWKxdDxao56n/GCHHU0YQVdwpn7L2Pshhiqiizq1unxhJkw2ehtNo3ihiRvRsqidm8dU3hsQCMwcwROKqYelV8ZDzdQbGXj7ptNCaTZW5mvkdzbm6RO+jr+P9NvRi9M8w3b8YLCjxR0kn1xhxBYNfEU9F++emf7oc/YwqS9WoqDWY2HDeYHGYtKK6znPcJyOkMdUrk6xKr5q5NbpOxRMa38iNPiOZapp+XM+hvTPKEG6KC53U0P/JvdOexKY2uLE83T8xPEHaxzMbSoqjxbKP8AbAPe7Zd0Vr46nvKt1tUrHuFhPDmbTmeZdcY4gtT0Ei+VUpqd4Lr7oZNGUBtr0/SJgTpNR5NMn7OHUe0zP/q3+233KfGbzPSYgymAww/fp3tGKeDobq6ekZrjppd6d9Ee4yDTtPeq9tBh7DL526TxhvaOFp7qqHtWbClS4EHqInKrpuj/ALXosPbCppRD5LUh2fnNRrWj2Txjt0+IoFkI6LjrE0NQTOD0hU1wQ1Nlvnq3v7ZpdP4qph8cl2vQrbtwY/n7Z6dLV8o5Ymk54P1BFagj70idgi9TDv5pndza6oIrVE2NTCv5pi1TB1PNMDXmSMnBVfMMkDuFWEAmFEIomhAJXE1lpo1RzZUVmY9AF4UCIYxeerph9qU9XEYjgQD+yQ9bAm3BOmS04jLVYzIujg1Giarj9tVPOOD9Fm2L/KLCI1apJzOfT8I/pmrkFuozubn3b5pmqDZdmPBQVHcM583WmZth3r2MCP7KB6zI9ULmxVR/GxPqvABXbYpA6WCey7SyYQA3LIp/gUFvSa5nOKtZXXFqfIFR/sIFX0jaVOIbzKY/+yqXPcsOKCbwz/bLEdxy9UKjAbAi9RA9kuELKtVt6j7GH97Qi4d97t6FAe6G5z+IdgJmQ3S3o2gD5hvP9KnSPstMqXXep6i1M9xuITW6W9GY1ukdotIqpYN5Qs3G2q3waVdjYBjcA3VxtQwluIt6wZCnzxmZV0micXzlLxvKSwbp6YZcQtKgrtuppYcTaaDQ1bm6mqdjKw9WUxp/FFilFdiKt+u07xrTFPv0Y8Imfonjse9Z9Y3J3KNgEWanfy27AAbdQ2DtvCIlhYdttp64ZMM25bdJ2+ucIhqZK81T2lC54uWb1ZCFV7eTTA+yiiMDBk7WPYSPZaZOATfn1lj750xKZLGs/mt2BfhKNiiNocddO/ujZwFPgPXKnBKNlx1M3xjxlMkGxSHaafUygSj00O2mh6Rl7DH3wvTf7QBilTR67QoHShKn1RiV4I1MLQP0SvUfiIB9F0z5Ld4t6xHKmEYbHYdDAN69vrgHSqNqq3SCVPrvLmUxAWCwj0nuBccVN43yn0d/iMOSMnC6yneGHyIocTbylqL02LDvBmx0XjBU1qevr3W4BOY7DOlL84lPTmFeS2kf8RhlY+Wl6dQcHWbYicboyr/g9JvRawpYvNQNgqfR6icx2idpPdScwxq1xbj0nkJhBssORBsJpyAtMy9piBshCLKCEWBXEV1pozt5KKSbZk9A6Tsiujf2VMs41q9ZzVratiA5AAS+8KoVR9ma/TWODVloA+LT1atXgWz5tPUWPUsouKHGebW1OcQ7VriDVWmzMWO09Kj2TAoHdqj1wQxi+cO+Z/xyecveJ5sNjjDk7TLrh/4j2ZRU6SpDbUX0hKnTWHG2qnpCPE5PjDpCCkvCar9IcKP3q9mco3KjDD6RPZL4riW7CDhLBRwnPHlXQ3X9fwlf0spcP+f4Y8Twt06PUHCQ014Tm/0upcD2BvhMfpfR81+4yTX6a279T+nR8wvSOqY5kDYe+c+vK+ifouOsD4zNTlVQ1Sb2IBsCVBOR2Z9ERp54iCaXiMzDcVayIblgCLHbuvb3ytGzFiTcljfrnhvKjlNWxVYlHZaSnxNUst+m18o9yY5aVqBCVyXp7A21l2bejp2ztP8AGjHHq5+UZw9uRQNgmbmcVV8IWGyp0jzj82zs4B5tLbiTYnsmpxPK/E1L6mKw9PhalresvOO3Z0rSbRmHpRPTKGqo2sO8TynE6RxlT/5LsWkqj2ma6qmNb/PMenWZfYJuNP7Nq/xeynEJ5w7xMCsnnDvE8SqaOxZ/zZPXiKg90A2icUNlcnqrtNbcdszS8f4y911hxlGniVFNKU7FK1Ubv/fVh6zNnheUemKe0CqAbeMgY96xtdSzzHrD1ZoB6YPzacJQ5f11yr4N+umT7GAmzw/LvBtbX52kT/qU2A7xcTM6duky6CpQ4Xi6JqOHCrcb7WMHhtO4WqP2dem3QHF+6MGsDvBmMYVqeW+EFXDjEU8qlJgwa9itszlx2HsE32gNJDFYanW+ky2qAbqi5MO/PqIi61FsyG2q4sd9jxtOd5JVzhMZVwTmyVW1qW4a4GQHWuX8onq0rtTHlpzHvHP+vd3JlGlzKNPQ8ockkko2SwiiCWGWByuM5DirVescVUDVHLkaim3Abdwygv1eHdjKn3a/GdohhlMz4V6dd/U7cIfBw311/ul+MqfBq/11vuV+M9BUwgjbr0v5Gp8nnJ8GdT66fuF/FKnwY1frx+4X8U9LEsI269H5Gp8peYnwYV/r5+4H4pU+C7EfXz9wPjPUhLAS7dek/I1PlLyk+CzE/wDkP6H/AGlT4KsT/wCQ/o/9p6yBM2jbr0b+p8peRnwUYr6//SP4pU+CbFfX/wCm34p6/aZtG3XpN6/bxxvBHij/AJ4eg/4pV/BDiCuq2Ip1LEkEh0YX2553E9ltJaXbqb1+3iD+BvEbq1PtY/hg/wBTmL/1qXe3wnuVpLSbcG9PUfp4nQ8EmMS+rUo6zArrMzNYHbYACC/U3ifrFL0G+M9ytMWjbgnVtLw39T2K/wBel3MJj9UmMGyvT76gnuNpgrL4QzuWeH/qr0gNldPTqTB8GWkxsrU/Tb4T28rKlZNuGt23bxA+DnSo/e0j/P8A9ZX9ANMDY9H0/wAp7eUlSkm3Vd+/bxE8idND/RP/AOh+EjckNM2sUosOHO39ontZQShWNuq/kX7eJHkbpTfhqB/nT3iXpcmNKp5OHC/Yrgeq4ns5WDYSbcG/b6/Tyeno3TC/uGPXUpn3yuO0ZpSqabNhmV6JvTdSmsM7j6Wy89WYQDSbVVjXtHtH6I4bXKKXXVcqpdeDWzEyyxhhBPOjgBaZmZIQ0rQqvJJCiK0MrySQgqvLq8kkoIHlw8kkCwaWDSSSi2tM60kkDOtJrTMkCa0mtJJKjGtJrSSQJrSa0kkDGtMa0kkisFpUtJJAqWlS0kkChaULSSSAbNBM8zJAC7QLNJJIBM0C7SSQBFpJJIH/2Q==","description":"asdfgb","price":"6352","id":"0.4961980477018628"}] \ No newline at end of file +[ + { + "title": "wer", + "imageUrl": "asdf", + "description": "ertfygh", + "price": "54", + "id": "1.1949186432461922" + }, + { + "title": "wefr", + "imageUrl": "desf", + "description": "4et5y", + "price": "3521", + "id": "2" + }, + { + "title": "asdfg", + "imageUrl": "asdf", + "description": "", + "price": "65", + "id": "1.6094309610182131" + }, + { + "title": "sdfg", + "imageUrl": "sd", + "description": "", + "price": "5823", + "id": "0.3689965042774357" + }, + { + "title": "sdg", + "imageUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8QDxIPDxAQEA8PDQ0PDw8PDw8PEBAPFREWFhUVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGC8iHSUtLSsrLS0rLS0rMC4rLTAtLS0rLSstLS0tLS0rLS0tLzUtLS0tLSstLS0tLS0tLS0rK//AABEIALcBEwMBIgACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAADBAACAQUGB//EAEkQAAIBAgIFBgoGCAYBBQAAAAECAAMRBCEFEjFBUQYTYXGBkQciMlKSobHB0fBCVHKT0uEWFyNDYoKj8RREU2Oy4lUVM0Vzg//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/EACgRAQACAQQBBAIBBQAAAAAAAAABAhEDEyFREjFBUmEUkQQiMkKBof/aAAwDAQACEQMRAD8A8vUQirIohVWBFWECyKsKqwMKsIqyyrCKsCqrCqksqQirAqqy4WXVYRUgUCS4SEVIQJAEElgkKElwkAISZCQ4SWCQF9SZ1IxqSakBbUk1IzqSakBXUmCkZ1JgpAVKShSNlJQpAUKShWNlIMpAUKyjLGmSDZYCrJBssaZYNlgKssEyxplg2WAqywTLGmWCZYC+rJCFZmBFWEVZFWFVYEVYVVmVWFVYGFWFVZlVhVWBhVhVSWRIVVgVVIRUl1SEVIFFSXCQqpCKkAQSXFOGCS4SAAU5YJGAksEgLakzqRnm5nm4CupMaka5uTm4ChSVKRwpKlICRpyhSOlINkgJMkoyRxkg2SAmywTJHGSCZICbLBsscZIFkgKMsEyxtlgmWAoywTLGmWCZYC1pIUrJAirCqswohkWBlFhVWRVhkWBFWGRZEWGVYGFWGVZlVhkSBVUhlSWVIZUgUVIRUnUaD0ErUi9UZ1B4o4Lxmv0loh6LcU3N8YyNWqQgpwqpCBIAAksKcOElwkBfm", + "description": "dfgnvh", + "price": "5555", + "id": "111" + }, + { + "title": "asdf", + "imageUrl": "data:image/jpeg;base64,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", + "description": "asdfgb", + "price": "6352", + "id": "123" + } +] diff --git a/views/admin/edit-product.ejs b/views/admin/edit-product.ejs index 1b4e95e..13a5bc3 100644 --- a/views/admin/edit-product.ejs +++ b/views/admin/edit-product.ejs @@ -7,25 +7,35 @@ <%- include('../includes/navigation.ejs') %>
    -
    + + +
    - +
    - +
    - + <%= product.price %> <%} %>>
    - +
    - +
    <%- include('../includes/end.ejs') %> \ No newline at end of file From 2cb5f2210fc1715280105f2402f43ae8e3cf39c9 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Thu, 16 Jan 2020 23:12:38 +0530 Subject: [PATCH 23/50] 122 Linking to the Edit Page --- controller/admin.js | 7 ++++--- notes.txt | 15 ++++++++++++++- routes/admin.js | 2 ++ views/admin/edit-product.ejs | 13 ++----------- views/admin/products.ejs | 3 ++- 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index 349fbb4..f919686 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -26,10 +26,7 @@ exports.getEditProduct = (req, res, next) => { res.redirect('/'); } - // taking out productID from the dynamic parameters which we are passing in url const productID = req.params.productID; - // console.log(productID); - Product.findById(productID, product => { res.render("admin/edit-product", { path: "/admin/edit-product", @@ -41,6 +38,10 @@ exports.getEditProduct = (req, res, next) => { }; +exports.postEditProduct = (req, res, next) => { + res.redirect('/'); +}; + exports.getProducts = (req, res, next) => { Product.fetchAll((products) => { res.render("admin/products", { diff --git a/notes.txt b/notes.txt index d5bb9e7..a33758e 100644 --- a/notes.txt +++ b/notes.txt @@ -35,4 +35,17 @@ npm install --save ejs pug express-handlebars pug: -html syntax is different but if we inspect page, it will shows us proper html code \ No newline at end of file +html syntax is different but if we inspect page, it will shows us proper html code + + + + \ No newline at end of file diff --git a/routes/admin.js b/routes/admin.js index 70a4bec..6296017 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -12,5 +12,7 @@ routes.post('/add-product', adminController.postAddProduct); routes.get('/edit-product/:productID', adminController.getEditProduct); +routes.post('/edit-product', adminController.postEditProduct); + routes.get('/products',adminController.getProducts) module.exports = routes; diff --git a/views/admin/edit-product.ejs b/views/admin/edit-product.ejs index 13a5bc3..216d2bf 100644 --- a/views/admin/edit-product.ejs +++ b/views/admin/edit-product.ejs @@ -7,17 +7,8 @@ <%- include('../includes/navigation.ejs') %>
    - - -
    + +
    diff --git a/views/admin/products.ejs b/views/admin/products.ejs index 13827f6..e4569c4 100644 --- a/views/admin/products.ejs +++ b/views/admin/products.ejs @@ -27,7 +27,8 @@

    - Edit + + Edit From da2a4c3491f2da22728290d870d1a9da2c1b4fdc Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Thu, 16 Jan 2020 23:57:38 +0530 Subject: [PATCH 24/50] 123 Editing the Product Data --- controller/admin.js | 13 +++++++++-- data/products.json | 45 +----------------------------------- model/product.js | 34 +++++++++++++++++++++------ views/admin/edit-product.ejs | 7 +++++- 4 files changed, 45 insertions(+), 54 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index f919686..163c07c 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -14,7 +14,8 @@ exports.postAddProduct = (req, res, next) => { const description = req.body.description; const price = req.body.price; - const product = new Product(title, imageUrl, description, price); + // passing null value in id parameter of constructor of a class + const product = new Product(null, title, imageUrl, description, price); product.save(); res.redirect("/"); @@ -39,7 +40,15 @@ exports.getEditProduct = (req, res, next) => { }; exports.postEditProduct = (req, res, next) => { - res.redirect('/'); + const productID = req.body.productID; + const updatedTitle = req.body.title; + const updatedImageUrl = req.body.imageUrl; + const updatedPrice = req.body.price; + const upadatedDesciption = req.body.description; + + const updatedProduct = new Product(productID, updatedTitle, updatedImageUrl, upadatedDesciption, updatedPrice); + updatedProduct.save(); + res.redirect('/admin/products'); }; exports.getProducts = (req, res, next) => { diff --git a/data/products.json b/data/products.json index d845810..de387f0 100644 --- a/data/products.json +++ b/data/products.json @@ -1,44 +1 @@ -[ - { - "title": "wer", - "imageUrl": "asdf", - "description": "ertfygh", - "price": "54", - "id": "1.1949186432461922" - }, - { - "title": "wefr", - "imageUrl": "desf", - "description": "4et5y", - "price": "3521", - "id": "2" - }, - { - "title": "asdfg", - "imageUrl": "asdf", - "description": "", - "price": "65", - "id": "1.6094309610182131" - }, - { - "title": "sdfg", - "imageUrl": "sd", - "description": "", - "price": "5823", - "id": "0.3689965042774357" - }, - { - "title": "sdg", - "imageUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8QDxIPDxAQEA8PDQ0PDw8PDw8PEBAPFREWFhUVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGC8iHSUtLSsrLS0rLS0rMC4rLTAtLS0rLSstLS0tLS0rLS0tLzUtLS0tLSstLS0tLS0tLS0rK//AABEIALcBEwMBIgACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAADBAACAQUGB//EAEkQAAIBAgIFBgoGCAYBBQAAAAECAAMRBCEFEjFBUQYTYXGBkQciMlKSobHB0fBCVHKT0uEWFyNDYoKj8RREU2Oy4lUVM0Vzg//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/EACgRAQACAQQBBAIBBQAAAAAAAAABAhEDEyFREjFBUmEUkQQiMkKBof/aAAwDAQACEQMRAD8A8vUQirIohVWBFWECyKsKqwMKsIqyyrCKsCqrCqksqQirAqqy4WXVYRUgUCS4SEVIQJAEElgkKElwkAISZCQ4SWCQF9SZ1IxqSakBbUk1IzqSakBXUmCkZ1JgpAVKShSNlJQpAUKShWNlIMpAUKyjLGmSDZYCrJBssaZYNlgKssEyxplg2WAqywTLGmWCZYC+rJCFZmBFWEVZFWFVYEVYVVmVWFVYGFWFVZlVhVWBhVhVSWRIVVgVVIRUl1SEVIFFSXCQqpCKkAQSXFOGCS4SAAU5YJGAksEgLakzqRnm5nm4CupMaka5uTm4ChSVKRwpKlICRpyhSOlINkgJMkoyRxkg2SAmywTJHGSCZICbLBsscZIFkgKMsEyxtlgmWAoywTLGmWCZYC1pIUrJAirCqswohkWBlFhVWRVhkWBFWGRZEWGVYGFWGVZlVhkSBVUhlSWVIZUgUVIRUnUaD0ErUi9UZ1B4o4Lxmv0loh6LcU3N8YyNWqQgpwqpCBIAAksKcOElwkBfm", - "description": "dfgnvh", - "price": "5555", - "id": "111" - }, - { - "title": "asdf", - "imageUrl": "data:image/jpeg;base64,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", - "description": "asdfgb", - "price": "6352", - "id": "123" - } -] +[{"id":"1.1949186432461922","title":" wer ","imageUrl":" data:image/jpeg;base64,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 ","description":" ertfygh ","price":"54"},{"id":"2","title":" wefr ","imageUrl":" data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8QDxIPDxAQEA8PDQ0PDw8PDw8PEBAPFREWFhUVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGC8iHSUtLSsrLS0rLS0rMC4rLTAtLS0rLSstLS0tLS0rLS0tLzUtLS0tLSstLS0tLS0tLS0rK//AABEIALcBEwMBIgACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAADBAACAQUGB//EAEkQAAIBAgIFBgoGCAYBBQAAAAECAAMRBCEFEjFBUQYTYXGBkQciMlKSobHB0fBCVHKT0uEWFyNDYoKj8RREU2Oy4lUVM0Vzg//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/EACgRAQACAQQBBAIBBQAAAAAAAAABAhEDEyFREjFBUmEUkQQiMkKBof/aAAwDAQACEQMRAD8A8vUQirIohVWBFWECyKsKqwMKsIqyyrCKsCqrCqksqQirAqqy4WXVYRUgUCS4SEVIQJAEElgkKElwkAISZCQ4SWCQF9SZ1IxqSakBbUk1IzqSakBXUmCkZ1JgpAVKShSNlJQpAUKShWNlIMpAUKyjLGmSDZYCrJBssaZYNlgKssEyxplg2WAqywTLGmWCZYC+rJCFZmBFWEVZFWFVYEVYVVmVWFVYGFWFVZlVhVWBhVhVSWRIVVgVVIRUl1SEVIFFSXCQqpCKkAQSXFOGCS4SAAU5YJGAksEgLakzqRnm5nm4CupMaka5uTm4ChSVKRwpKlICRpyhSOlINkgJMkoyRxkg2SAmywTJHGSCZICbLBsscZIFkgKMsEyxtlgmWAoywTLGmWCZYC1pIUrJAirCqswohkWBlFhVWRVhkWBFWGRZEWGVYGFWGVZlVhkSBVUhlSWVIZUgUVIRUnUaD0ErUi9UZ1B4o4Lxmv0loh6LcU3N8YyNWqQgpwqpCBIAAksKcOElwkBfm5ObjOpM6kBXm5Cka1JjUgKGnKlI4UlCkBMpBskdKQbJASZIJkjzJBMkBFkgmSOskE6QEWWCZY46QLLATdYFljjrAusBR1gWWNusC6wFtWSE1ZmBVRDosogh0ECyrDIsqiw6LAsiwyLMIsOiwMokMiSIsOiQIiTccn9F8/VzH7NLM548F7fdE8HhWqOqILsxsJ6DozALQpCmuZGbN5zHaYBQlsoDEUww1SLjeI42UXZe2TCuZ0hogr41PNd67xNeEnaFZrcdo5W8ZRZuG4wjQBJYU4waRBsRmJkJKF+bmebjISTUgLc3MGnGtSTUgKGnKFI4UlSkBJkg2SOskNhtHs/QvGBq6WGZzqqLmF0pos0QpJvrXv0GdZgMKlMWUZ8d8rpvCc5QYfSUa69Y/K8mVcCyQLpHmSBdJUIusA6R50gHWAi6wLrHHWAdYCbrAusbdYB1gLFZIQiSBVBDoJRBDosC6LDosogjCLAsixhFlUWMIsCyLDosqizY6KwjVaqIu9gTlcBRmSYHS8ltF82nPOPHceKD9FPiZ0FphCNky97ZSwAVDnnlnYbfZ7x27JRWB/t1QrL7Nmz1fO2U5vhtzy4G27o/OFVtBssKDllsy2X4ZDp+eMwyyDW4vDBs/pe2a/Um+qrEsTQ3jbINfqzOrDakzqSoBqzGrGNSQpAWKTHN3yEdp4Yt0DjHKGGC7NvGAlhtHja+fRNilLcBCrT3nZCWy4C3zeRQ1UDp49EKVlBnkMhuPHLd22hkGUuByentGhBrKLAH1HZ8JoHSehaQw4dCp+kCPhOFrUipKnIgkEdIkgIOkXdY86xd1lQjUWLusedYvUWAk6wDrG3WAcQFbSQhWSBRBDoIOmIwggEQRimsEgjNNYBUWMIsHTEYprALSS+W8zt9A6NFFNYj9o6i54DbaaHk3o/nKmuR4lPM9LbhOyJklYDrPYX9xPslcNj1J1WyuSFJIz+ffAYh77xwFs2E19Ubd195zPbOc3w1jLoWThsgynC3rHrmlwulmpmzXZOnyh0ze0aiVAHQ3Hztm6Xi3ozMTChS/Xnnlfjn8RBbP7kjYeiHZbStgfy93CbQBlgqiw7A7877+3ZaUYXmZUg6ZzGrD1ltJqxCAakPSw+890vSpxlE+eMKqqQir87pbs7L59smqT0WAyA7+rdLhGD3n537pnUzuTwsNo+cv7y6oNgG83y+c4QL35bZQIJxyGVhJWqqguxAEV0hpRKWQ8Z9w3DrM0Zq1KrazEm+zcoHQJx1NeteI5luKTLcLiecN9g3CaTlDhLOKg2OLH7Q/KbOgAguxA+dwimlsVr0yqjxbgknb2RS0z6loc06xeosedYtUWdWCNRYvUWO1Fi1QQEqixZxHagiziAsVmIQiSAKmIwggUEYQQD0xGaYgKYjVMQDUxGaYgaYm10RgjVqKLeJe7HoG34dsDqNCXp4dAQBca1gLbdl+mMVsfSHiu2rfje3fumKrTQY6oSSTv2DiOqcbXw6RDfAI/kOp6iIvXwreszka175EhrnMHMZ/O2SjpPEpktV+gMdb2zjOpHvDWHQVsOw7uv2wWHxNSg2svap2N1zXJynrjy0puBtJBUxqnyjw7ZVKb0zxHjj1Zznx6xKutwGkKdcZZMNqnaIdqc5ajzdTx8PVRmGd1azDrE3GC0kTZKw1W2Btx656dPXzxdi1OjpAtY/C+7b74Jltl6/yjTLv3WgGXd3T0S5l6yZdUGNwjDDKBw2ec55xw1gxTSXJtx6+nok+HXLIntvNwigS/XcdIv0Q6px7pYCw9pM1mK0tYlaQ123t9EfGZvqVpGbSsRM+jYYmulNdaowVemaHG6XqVfEogouzXPlHqG6anSemMPTa9etzlQfQTx2HYMlnPY7lVVe60FFBfOPjVPgJ5L6178RxH/XSKxDpqopURrVnAJzsTdj2RCpyivlRXUHnuASd2WfzacgFZm12Ys227azHtmxwyWyvl0g7e6ZpWIJl0mDrl82YsdtzNkq3FjvmkwCEMCOo57pu6U9EMtRXp2JHA2itRZt9JUtjccj1zWVBO7mSqLFagj1QRWoICVQRWoI7UEVqCAsRMS5EkANOMUxNgnJ3Efw+lDJoCv/AA98BOmIzTEbTQdbgvfDpoetwHfAXp7ukgDrM7bRWHWlTFyASN5tOX0bo5mxSq3k0gHbeNY5KPfNzpLFHW1beTsABM4a2p4ulatrWAOx17xEamAvtcdrCal8Qd4I62VYE1VP0b9tR55Z1pn2dfCGxfRlEeVVQdbQTYLC766d94mGG6kvaqj2mFUvuRB3e5ZnynpfGBTgcKf3yeuDfQ1FhZatM/zWmb1OKDv+Ex45+lS7f7SZ+jBZ+Tj7UIuNjI2YhKWKxdDxao56n/GCHHU0YQVdwpn7L2Pshhiqiizq1unxhJkw2ehtNo3ihiRvRsqidm8dU3hsQCMwcwROKqYelV8ZDzdQbGXj7ptNCaTZW5mvkdzbm6RO+jr+P9NvRi9M8w3b8YLCjxR0kn1xhxBYNfEU9F++emf7oc/YwqS9WoqDWY2HDeYHGYtKK6znPcJyOkMdUrk6xKr5q5NbpOxRMa38iNPiOZapp+XM+hvTPKEG6KC53U0P/JvdOexKY2uLE83T8xPEHaxzMbSoqjxbKP8AbAPe7Zd0Vr46nvKt1tUrHuFhPDmbTmeZdcY4gtT0Ei+VUpqd4Lr7oZNGUBtr0/SJgTpNR5NMn7OHUe0zP/q3+233KfGbzPSYgymAww/fp3tGKeDobq6ekZrjppd6d9Ee4yDTtPeq9tBh7DL526TxhvaOFp7qqHtWbClS4EHqInKrpuj/ALXosPbCppRD5LUh2fnNRrWj2Txjt0+IoFkI6LjrE0NQTOD0hU1wQ1Nlvnq3v7ZpdP4qph8cl2vQrbtwY/n7Z6dLV8o5Ymk54P1BFagj70idgi9TDv5pndza6oIrVE2NTCv5pi1TB1PNMDXmSMnBVfMMkDuFWEAmFEIomhAJXE1lpo1RzZUVmY9AF4UCIYxeerph9qU9XEYjgQD+yQ9bAm3BOmS04jLVYzIujg1Giarj9tVPOOD9Fm2L/KLCI1apJzOfT8I/pmrkFuozubn3b5pmqDZdmPBQVHcM583WmZth3r2MCP7KB6zI9ULmxVR/GxPqvABXbYpA6WCey7SyYQA3LIp/gUFvSa5nOKtZXXFqfIFR/sIFX0jaVOIbzKY/+yqXPcsOKCbwz/bLEdxy9UKjAbAi9RA9kuELKtVt6j7GH97Qi4d97t6FAe6G5z+IdgJmQ3S3o2gD5hvP9KnSPstMqXXep6i1M9xuITW6W9GY1ukdotIqpYN5Qs3G2q3waVdjYBjcA3VxtQwluIt6wZCnzxmZV0micXzlLxvKSwbp6YZcQtKgrtuppYcTaaDQ1bm6mqdjKw9WUxp/FFilFdiKt+u07xrTFPv0Y8Imfonjse9Z9Y3J3KNgEWanfy27AAbdQ2DtvCIlhYdttp64ZMM25bdJ2+ucIhqZK81T2lC54uWb1ZCFV7eTTA+yiiMDBk7WPYSPZaZOATfn1lj750xKZLGs/mt2BfhKNiiNocddO/ujZwFPgPXKnBKNlx1M3xjxlMkGxSHaafUygSj00O2mh6Rl7DH3wvTf7QBilTR67QoHShKn1RiV4I1MLQP0SvUfiIB9F0z5Ld4t6xHKmEYbHYdDAN69vrgHSqNqq3SCVPrvLmUxAWCwj0nuBccVN43yn0d/iMOSMnC6yneGHyIocTbylqL02LDvBmx0XjBU1qevr3W4BOY7DOlL84lPTmFeS2kf8RhlY+Wl6dQcHWbYicboyr/g9JvRawpYvNQNgqfR6icx2idpPdScwxq1xbj0nkJhBssORBsJpyAtMy9piBshCLKCEWBXEV1pozt5KKSbZk9A6Tsiujf2VMs41q9ZzVratiA5AAS+8KoVR9ma/TWODVloA+LT1atXgWz5tPUWPUsouKHGebW1OcQ7VriDVWmzMWO09Kj2TAoHdqj1wQxi+cO+Z/xyecveJ5sNjjDk7TLrh/4j2ZRU6SpDbUX0hKnTWHG2qnpCPE5PjDpCCkvCar9IcKP3q9mco3KjDD6RPZL4riW7CDhLBRwnPHlXQ3X9fwlf0spcP+f4Y8Twt06PUHCQ014Tm/0upcD2BvhMfpfR81+4yTX6a279T+nR8wvSOqY5kDYe+c+vK+ifouOsD4zNTlVQ1Sb2IBsCVBOR2Z9ERp54iCaXiMzDcVayIblgCLHbuvb3ytGzFiTcljfrnhvKjlNWxVYlHZaSnxNUst+m18o9yY5aVqBCVyXp7A21l2bejp2ztP8AGjHHq5+UZw9uRQNgmbmcVV8IWGyp0jzj82zs4B5tLbiTYnsmpxPK/E1L6mKw9PhalresvOO3Z0rSbRmHpRPTKGqo2sO8TynE6RxlT/5LsWkqj2ma6qmNb/PMenWZfYJuNP7Nq/xeynEJ5w7xMCsnnDvE8SqaOxZ/zZPXiKg90A2icUNlcnqrtNbcdszS8f4y911hxlGniVFNKU7FK1Ubv/fVh6zNnheUemKe0CqAbeMgY96xtdSzzHrD1ZoB6YPzacJQ5f11yr4N+umT7GAmzw/LvBtbX52kT/qU2A7xcTM6duky6CpQ4Xi6JqOHCrcb7WMHhtO4WqP2dem3QHF+6MGsDvBmMYVqeW+EFXDjEU8qlJgwa9itszlx2HsE32gNJDFYanW+ky2qAbqi5MO/PqIi61FsyG2q4sd9jxtOd5JVzhMZVwTmyVW1qW4a4GQHWuX8onq0rtTHlpzHvHP+vd3JlGlzKNPQ8ockkko2SwiiCWGWByuM5DirVescVUDVHLkaim3Abdwygv1eHdjKn3a/GdohhlMz4V6dd/U7cIfBw311/ul+MqfBq/11vuV+M9BUwgjbr0v5Gp8nnJ8GdT66fuF/FKnwY1frx+4X8U9LEsI269H5Gp8peYnwYV/r5+4H4pU+C7EfXz9wPjPUhLAS7dek/I1PlLyk+CzE/wDkP6H/AGlT4KsT/wCQ/o/9p6yBM2jbr0b+p8peRnwUYr6//SP4pU+CbFfX/wCm34p6/aZtG3XpN6/bxxvBHij/AJ4eg/4pV/BDiCuq2Ip1LEkEh0YX2553E9ltJaXbqb1+3iD+BvEbq1PtY/hg/wBTmL/1qXe3wnuVpLSbcG9PUfp4nQ8EmMS+rUo6zArrMzNYHbYACC/U3ifrFL0G+M9ytMWjbgnVtLw39T2K/wBel3MJj9UmMGyvT76gnuNpgrL4QzuWeH/qr0gNldPTqTB8GWkxsrU/Tb4T28rKlZNuGt23bxA+DnSo/e0j/P8A9ZX9ANMDY9H0/wAp7eUlSkm3Vd+/bxE8idND/RP/AOh+EjckNM2sUosOHO39ontZQShWNuq/kX7eJHkbpTfhqB/nT3iXpcmNKp5OHC/Yrgeq4ns5WDYSbcG/b6/Tyeno3TC/uGPXUpn3yuO0ZpSqabNhmV6JvTdSmsM7j6Wy89WYQDSbVVjXtHtH6I4bXKKXXVcqpdeDWzEyyxhhBPOjgBaZmZIQ0rQqvJJCiK0MrySQgqvLq8kkoIHlw8kkCwaWDSSSi2tM60kkDOtJrTMkCa0mtJJKjGtJrSSQJrSa0kkDGtMa0kkisFpUtJJAqWlS0kkChaULSSSAbNBM8zJAC7QLNJJIBM0C7SSQBFpJJIH/2Q== ","description":" 4et5y ","price":"3521"},{"id":"1.6094309610182131","title":" asdfg ","imageUrl":" data:image/jpeg;base64,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 ","description":" ","price":"65"},{"id":"0.3689965042774357","title":" sdfg ","imageUrl":" data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8QDxIPDxAQEA8PDQ0PDw8PDw8PEBAPFREWFhUVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGC8iHSUtLSsrLS0rLS0rMC4rLTAtLS0rLSstLS0tLS0rLS0tLzUtLS0tLSstLS0tLS0tLS0rK//AABEIALcBEwMBIgACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAADBAACAQUGB//EAEkQAAIBAgIFBgoGCAYBBQAAAAECAAMRBCEFEjFBUQYTYXGBkQciMlKSobHB0fBCVHKT0uEWFyNDYoKj8RREU2Oy4lUVM0Vzg//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/EACgRAQACAQQBBAIBBQAAAAAAAAABAhEDEyFREjFBUmEUkQQiMkKBof/aAAwDAQACEQMRAD8A8vUQirIohVWBFWECyKsKqwMKsIqyyrCKsCqrCqksqQirAqqy4WXVYRUgUCS4SEVIQJAEElgkKElwkAISZCQ4SWCQF9SZ1IxqSakBbUk1IzqSakBXUmCkZ1JgpAVKShSNlJQpAUKShWNlIMpAUKyjLGmSDZYCrJBssaZYNlgKssEyxplg2WAqywTLGmWCZYC+rJCFZmBFWEVZFWFVYEVYVVmVWFVYGFWFVZlVhVWBhVhVSWRIVVgVVIRUl1SEVIFFSXCQqpCKkAQSXFOGCS4SAAU5YJGAksEgLakzqRnm5nm4CupMaka5uTm4ChSVKRwpKlICRpyhSOlINkgJMkoyRxkg2SAmywTJHGSCZICbLBsscZIFkgKMsEyxtlgmWAoywTLGmWCZYC1pIUrJAirCqswohkWBlFhVWRVhkWBFWGRZEWGVYGFWGVZlVhkSBVUhlSWVIZUgUVIRUnUaD0ErUi9UZ1B4o4Lxmv0loh6LcU3N8YyNWqQgpwqpCBIAAksKcOElwkBfm5ObjOpM6kBXm5Cka1JjUgKGnKlI4UlCkBMpBskdKQbJASZIJkjzJBMkBFkgmSOskE6QEWWCZY46QLLATdYFljjrAusBR1gWWNusC6wFtWSE1ZmBVRDosogh0ECyrDIsqiw6LAsiwyLMIsOiwMokMiSIsOiQIiTccn9F8/VzH7NLM548F7fdE8HhWqOqILsxsJ6DozALQpCmuZGbN5zHaYBQlsoDEUww1SLjeI42UXZe2TCuZ0hogr41PNd67xNeEnaFZrcdo5W8ZRZuG4wjQBJYU4waRBsRmJkJKF+bmebjISTUgLc3MGnGtSTUgKGnKFI4UlSkBJkg2SOskNhtHs/QvGBq6WGZzqqLmF0pos0QpJvrXv0GdZgMKlMWUZ8d8rpvCc5QYfSUa69Y/K8mVcCyQLpHmSBdJUIusA6R50gHWAi6wLrHHWAdYCbrAusbdYB1gLFZIQiSBVBDoJRBDosC6LDosogjCLAsixhFlUWMIsCyLDosqizY6KwjVaqIu9gTlcBRmSYHS8ltF82nPOPHceKD9FPiZ0FphCNky97ZSwAVDnnlnYbfZ7x27JRWB/t1QrL7Nmz1fO2U5vhtzy4G27o/OFVtBssKDllsy2X4ZDp+eMwyyDW4vDBs/pe2a/Um+qrEsTQ3jbINfqzOrDakzqSoBqzGrGNSQpAWKTHN3yEdp4Yt0DjHKGGC7NvGAlhtHja+fRNilLcBCrT3nZCWy4C3zeRQ1UDp49EKVlBnkMhuPHLd22hkGUuByentGhBrKLAH1HZ8JoHSehaQw4dCp+kCPhOFrUipKnIgkEdIkgIOkXdY86xd1lQjUWLusedYvUWAk6wDrG3WAcQFbSQhWSBRBDoIOmIwggEQRimsEgjNNYBUWMIsHTEYprALSS+W8zt9A6NFFNYj9o6i54DbaaHk3o/nKmuR4lPM9LbhOyJklYDrPYX9xPslcNj1J1WyuSFJIz+ffAYh77xwFs2E19Ubd195zPbOc3w1jLoWThsgynC3rHrmlwulmpmzXZOnyh0ze0aiVAHQ3Hztm6Xi3ozMTChS/Xnnlfjn8RBbP7kjYeiHZbStgfy93CbQBlgqiw7A7877+3ZaUYXmZUg6ZzGrD1ltJqxCAakPSw+890vSpxlE+eMKqqQir87pbs7L59smqT0WAyA7+rdLhGD3n537pnUzuTwsNo+cv7y6oNgG83y+c4QL35bZQIJxyGVhJWqqguxAEV0hpRKWQ8Z9w3DrM0Zq1KrazEm+zcoHQJx1NeteI5luKTLcLiecN9g3CaTlDhLOKg2OLH7Q/KbOgAguxA+dwimlsVr0yqjxbgknb2RS0z6loc06xeosedYtUWdWCNRYvUWO1Fi1QQEqixZxHagiziAsVmIQiSAKmIwggUEYQQD0xGaYgKYjVMQDUxGaYgaYm10RgjVqKLeJe7HoG34dsDqNCXp4dAQBca1gLbdl+mMVsfSHiu2rfje3fumKrTQY6oSSTv2DiOqcbXw6RDfAI/kOp6iIvXwreszka175EhrnMHMZ/O2SjpPEpktV+gMdb2zjOpHvDWHQVsOw7uv2wWHxNSg2svap2N1zXJynrjy0puBtJBUxqnyjw7ZVKb0zxHjj1Zznx6xKutwGkKdcZZMNqnaIdqc5ajzdTx8PVRmGd1azDrE3GC0kTZKw1W2Btx656dPXzxdi1OjpAtY/C+7b74Jltl6/yjTLv3WgGXd3T0S5l6yZdUGNwjDDKBw2ec55xw1gxTSXJtx6+nok+HXLIntvNwigS/XcdIv0Q6px7pYCw9pM1mK0tYlaQ123t9EfGZvqVpGbSsRM+jYYmulNdaowVemaHG6XqVfEogouzXPlHqG6anSemMPTa9etzlQfQTx2HYMlnPY7lVVe60FFBfOPjVPgJ5L6178RxH/XSKxDpqopURrVnAJzsTdj2RCpyivlRXUHnuASd2WfzacgFZm12Ys227azHtmxwyWyvl0g7e6ZpWIJl0mDrl82YsdtzNkq3FjvmkwCEMCOo57pu6U9EMtRXp2JHA2itRZt9JUtjccj1zWVBO7mSqLFagj1QRWoICVQRWoI7UEVqCAsRMS5EkANOMUxNgnJ3Efw+lDJoCv/AA98BOmIzTEbTQdbgvfDpoetwHfAXp7ukgDrM7bRWHWlTFyASN5tOX0bo5mxSq3k0gHbeNY5KPfNzpLFHW1beTsABM4a2p4ulatrWAOx17xEamAvtcdrCal8Qd4I62VYE1VP0b9tR55Z1pn2dfCGxfRlEeVVQdbQTYLC766d94mGG6kvaqj2mFUvuRB3e5ZnynpfGBTgcKf3yeuDfQ1FhZatM/zWmb1OKDv+Ex45+lS7f7SZ+jBZ+Tj7UIuNjI2YhKWKxdDxao56n/GCHHU0YQVdwpn7L2Pshhiqiizq1unxhJkw2ehtNo3ihiRvRsqidm8dU3hsQCMwcwROKqYelV8ZDzdQbGXj7ptNCaTZW5mvkdzbm6RO+jr+P9NvRi9M8w3b8YLCjxR0kn1xhxBYNfEU9F++emf7oc/YwqS9WoqDWY2HDeYHGYtKK6znPcJyOkMdUrk6xKr5q5NbpOxRMa38iNPiOZapp+XM+hvTPKEG6KC53U0P/JvdOexKY2uLE83T8xPEHaxzMbSoqjxbKP8AbAPe7Zd0Vr46nvKt1tUrHuFhPDmbTmeZdcY4gtT0Ei+VUpqd4Lr7oZNGUBtr0/SJgTpNR5NMn7OHUe0zP/q3+233KfGbzPSYgymAww/fp3tGKeDobq6ekZrjppd6d9Ee4yDTtPeq9tBh7DL526TxhvaOFp7qqHtWbClS4EHqInKrpuj/ALXosPbCppRD5LUh2fnNRrWj2Txjt0+IoFkI6LjrE0NQTOD0hU1wQ1Nlvnq3v7ZpdP4qph8cl2vQrbtwY/n7Z6dLV8o5Ymk54P1BFagj70idgi9TDv5pndza6oIrVE2NTCv5pi1TB1PNMDXmSMnBVfMMkDuFWEAmFEIomhAJXE1lpo1RzZUVmY9AF4UCIYxeerph9qU9XEYjgQD+yQ9bAm3BOmS04jLVYzIujg1Giarj9tVPOOD9Fm2L/KLCI1apJzOfT8I/pmrkFuozubn3b5pmqDZdmPBQVHcM583WmZth3r2MCP7KB6zI9ULmxVR/GxPqvABXbYpA6WCey7SyYQA3LIp/gUFvSa5nOKtZXXFqfIFR/sIFX0jaVOIbzKY/+yqXPcsOKCbwz/bLEdxy9UKjAbAi9RA9kuELKtVt6j7GH97Qi4d97t6FAe6G5z+IdgJmQ3S3o2gD5hvP9KnSPstMqXXep6i1M9xuITW6W9GY1ukdotIqpYN5Qs3G2q3waVdjYBjcA3VxtQwluIt6wZCnzxmZV0micXzlLxvKSwbp6YZcQtKgrtuppYcTaaDQ1bm6mqdjKw9WUxp/FFilFdiKt+u07xrTFPv0Y8Imfonjse9Z9Y3J3KNgEWanfy27AAbdQ2DtvCIlhYdttp64ZMM25bdJ2+ucIhqZK81T2lC54uWb1ZCFV7eTTA+yiiMDBk7WPYSPZaZOATfn1lj750xKZLGs/mt2BfhKNiiNocddO/ujZwFPgPXKnBKNlx1M3xjxlMkGxSHaafUygSj00O2mh6Rl7DH3wvTf7QBilTR67QoHShKn1RiV4I1MLQP0SvUfiIB9F0z5Ld4t6xHKmEYbHYdDAN69vrgHSqNqq3SCVPrvLmUxAWCwj0nuBccVN43yn0d/iMOSMnC6yneGHyIocTbylqL02LDvBmx0XjBU1qevr3W4BOY7DOlL84lPTmFeS2kf8RhlY+Wl6dQcHWbYicboyr/g9JvRawpYvNQNgqfR6icx2idpPdScwxq1xbj0nkJhBssORBsJpyAtMy9piBshCLKCEWBXEV1pozt5KKSbZk9A6Tsiujf2VMs41q9ZzVratiA5AAS+8KoVR9ma/TWODVloA+LT1atXgWz5tPUWPUsouKHGebW1OcQ7VriDVWmzMWO09Kj2TAoHdqj1wQxi+cO+Z/xyecveJ5sNjjDk7TLrh/4j2ZRU6SpDbUX0hKnTWHG2qnpCPE5PjDpCCkvCar9IcKP3q9mco3KjDD6RPZL4riW7CDhLBRwnPHlXQ3X9fwlf0spcP+f4Y8Twt06PUHCQ014Tm/0upcD2BvhMfpfR81+4yTX6a279T+nR8wvSOqY5kDYe+c+vK+ifouOsD4zNTlVQ1Sb2IBsCVBOR2Z9ERp54iCaXiMzDcVayIblgCLHbuvb3ytGzFiTcljfrnhvKjlNWxVYlHZaSnxNUst+m18o9yY5aVqBCVyXp7A21l2bejp2ztP8AGjHHq5+UZw9uRQNgmbmcVV8IWGyp0jzj82zs4B5tLbiTYnsmpxPK/E1L6mKw9PhalresvOO3Z0rSbRmHpRPTKGqo2sO8TynE6RxlT/5LsWkqj2ma6qmNb/PMenWZfYJuNP7Nq/xeynEJ5w7xMCsnnDvE8SqaOxZ/zZPXiKg90A2icUNlcnqrtNbcdszS8f4y911hxlGniVFNKU7FK1Ubv/fVh6zNnheUemKe0CqAbeMgY96xtdSzzHrD1ZoB6YPzacJQ5f11yr4N+umT7GAmzw/LvBtbX52kT/qU2A7xcTM6duky6CpQ4Xi6JqOHCrcb7WMHhtO4WqP2dem3QHF+6MGsDvBmMYVqeW+EFXDjEU8qlJgwa9itszlx2HsE32gNJDFYanW+ky2qAbqi5MO/PqIi61FsyG2q4sd9jxtOd5JVzhMZVwTmyVW1qW4a4GQHWuX8onq0rtTHlpzHvHP+vd3JlGlzKNPQ8ockkko2SwiiCWGWByuM5DirVescVUDVHLkaim3Abdwygv1eHdjKn3a/GdohhlMz4V6dd/U7cIfBw311/ul+MqfBq/11vuV+M9BUwgjbr0v5Gp8nnJ8GdT66fuF/FKnwY1frx+4X8U9LEsI269H5Gp8peYnwYV/r5+4H4pU+C7EfXz9wPjPUhLAS7dek/I1PlLyk+CzE/wDkP6H/AGlT4KsT/wCQ/o/9p6yBM2jbr0b+p8peRnwUYr6//SP4pU+CbFfX/wCm34p6/aZtG3XpN6/bxxvBHij/AJ4eg/4pV/BDiCuq2Ip1LEkEh0YX2553E9ltJaXbqb1+3iD+BvEbq1PtY/hg/wBTmL/1qXe3wnuVpLSbcG9PUfp4nQ8EmMS+rUo6zArrMzNYHbYACC/U3ifrFL0G+M9ytMWjbgnVtLw39T2K/wBel3MJj9UmMGyvT76gnuNpgrL4QzuWeH/qr0gNldPTqTB8GWkxsrU/Tb4T28rKlZNuGt23bxA+DnSo/e0j/P8A9ZX9ANMDY9H0/wAp7eUlSkm3Vd+/bxE8idND/RP/AOh+EjckNM2sUosOHO39ontZQShWNuq/kX7eJHkbpTfhqB/nT3iXpcmNKp5OHC/Yrgeq4ns5WDYSbcG/b6/Tyeno3TC/uGPXUpn3yuO0ZpSqabNhmV6JvTdSmsM7j6Wy89WYQDSbVVjXtHtH6I4bXKKXXVcqpdeDWzEyyxhhBPOjgBaZmZIQ0rQqvJJCiK0MrySQgqvLq8kkoIHlw8kkCwaWDSSSi2tM60kkDOtJrTMkCa0mtJJKjGtJrSSQJrSa0kkDGtMa0kkisFpUtJJAqWlS0kkChaULSSSAbNBM8zJAC7QLNJJIBM0C7SSQBFpJJIH/2Q== ","description":" ","price":"5823"},{"id":"111","title":" sdg ","imageUrl":" data:image/jpeg;base64,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 ","description":" dfgnvh ","price":"5555"},{"id":"123","title":" asdf ","imageUrl":" data:image/jpeg;base64,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 ","description":" asdfgb ","price":"6352"},{"id":"0.47163532256635343","title":"book","imageUrl":" data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8QDxIPDxAQEA8PDQ0PDw8PDw8PEBAPFREWFhUVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGC8iHSUtLSsrLS0rLS0rMC4rLTAtLS0rLSstLS0tLS0rLS0tLzUtLS0tLSstLS0tLS0tLS0rK//AABEIALcBEwMBIgACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAADBAACAQUGB//EAEkQAAIBAgIFBgoGCAYBBQAAAAECAAMRBCEFEjFBUQYTYXGBkQciMlKSobHB0fBCVHKT0uEWFyNDYoKj8RREU2Oy4lUVM0Vzg//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/EACgRAQACAQQBBAIBBQAAAAAAAAABAhEDEyFREjFBUmEUkQQiMkKBof/aAAwDAQACEQMRAD8A8vUQirIohVWBFWECyKsKqwMKsIqyyrCKsCqrCqksqQirAqqy4WXVYRUgUCS4SEVIQJAEElgkKElwkAISZCQ4SWCQF9SZ1IxqSakBbUk1IzqSakBXUmCkZ1JgpAVKShSNlJQpAUKShWNlIMpAUKyjLGmSDZYCrJBssaZYNlgKssEyxplg2WAqywTLGmWCZYC+rJCFZmBFWEVZFWFVYEVYVVmVWFVYGFWFVZlVhVWBhVhVSWRIVVgVVIRUl1SEVIFFSXCQqpCKkAQSXFOGCS4SAAU5YJGAksEgLakzqRnm5nm4CupMaka5uTm4ChSVKRwpKlICRpyhSOlINkgJMkoyRxkg2SAmywTJHGSCZICbLBsscZIFkgKMsEyxtlgmWAoywTLGmWCZYC1pIUrJAirCqswohkWBlFhVWRVhkWBFWGRZEWGVYGFWGVZlVhkSBVUhlSWVIZUgUVIRUnUaD0ErUi9UZ1B4o4Lxmv0loh6LcU3N8YyNWqQgpwqpCBIAAksKcOElwk","description":"bookbook","price":"100"}] \ No newline at end of file diff --git a/model/product.js b/model/product.js index adb8ffa..33893dc 100644 --- a/model/product.js +++ b/model/product.js @@ -18,7 +18,9 @@ const getProductsFromFile = cb => { module.exports = class Product { - constructor(title, imageUrl, description, price) { + constructor(id,title, imageUrl, description, price) { + // it will a null value here + this.id = id; this.title = title; this.imageUrl = imageUrl; this.description = description; @@ -26,13 +28,31 @@ module.exports = class Product { } save() { - this.id = Math.random().toString(); getProductsFromFile((products) => { - products.push(this); - - fs.writeFile(p, JSON.stringify(products), (err) => { - console.log(err); - }); + // if id is defined. tis will be true only if we are editing product + if(this.id) { + const existingProductIndex = products.findIndex(prods => prods.id === this.id); + const updatedProduct = [...products]; + // "this" inside of this class is an updated product because we have imagined that we have created a new product instance. and we populate exisiting product by the newly created product instance. + updatedProduct[existingProductIndex] = this; + + // writing it to the file + // "updatedProduct" we have to save to the file as it contain edit product info + fs.writeFile(p, JSON.stringify(updatedProduct), (err) => { + // console.log(err); + + }); + } else { + // if the productID is "null" ie, we are creating new product instance and not editing + this.id = Math.random().toString(); + + products.push(this); + + fs.writeFile(p, JSON.stringify(products), (err) => { + console.log(err); + }); + } + }); }; diff --git a/views/admin/edit-product.ejs b/views/admin/edit-product.ejs index 216d2bf..6276854 100644 --- a/views/admin/edit-product.ejs +++ b/views/admin/edit-product.ejs @@ -8,7 +8,7 @@
    -
    +
    @@ -27,6 +27,11 @@
    + + + <% if (editing) {%> + <%} + %>
    <%- include('../includes/end.ejs') %> \ No newline at end of file From 1e2ec47f65bb76ba25c52ac526bc0aa1dd94044d Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Fri, 17 Jan 2020 02:12:04 +0530 Subject: [PATCH 25/50] 124 Adding the Product-Delete Functionality --- controller/admin.js | 6 ++++++ data/products.json | 2 +- model/product.js | 31 ++++++++++++++++++++++--------- routes/admin.js | 2 ++ views/admin/products.ejs | 1 + 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index 163c07c..695583f 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -51,6 +51,12 @@ exports.postEditProduct = (req, res, next) => { res.redirect('/admin/products'); }; +exports.postDeleteProduct = (req, res, next) => { + const productID = req.body.productID; + Product.deleteById(productID); + res.redirect('/admin/products'); +}; + exports.getProducts = (req, res, next) => { Product.fetchAll((products) => { res.render("admin/products", { diff --git a/data/products.json b/data/products.json index de387f0..8a0bba5 100644 --- a/data/products.json +++ b/data/products.json @@ -1 +1 @@ -[{"id":"1.1949186432461922","title":" wer ","imageUrl":" data:image/jpeg;base64,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 ","description":" ertfygh ","price":"54"},{"id":"2","title":" wefr ","imageUrl":" data:image/jpeg;base64,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 ","description":" 4et5y ","price":"3521"},{"id":"1.6094309610182131","title":" asdfg ","imageUrl":" data:image/jpeg;base64,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 ","description":" ","price":"65"},{"id":"0.3689965042774357","title":" sdfg ","imageUrl":" data:image/jpeg;base64,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 ","description":" ","price":"5823"},{"id":"111","title":" sdg ","imageUrl":" data:image/jpeg;base64,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 ","description":" dfgnvh ","price":"5555"},{"id":"123","title":" asdf ","imageUrl":" data:image/jpeg;base64,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 ","description":" asdfgb ","price":"6352"},{"id":"0.47163532256635343","title":"book","imageUrl":" data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8QDxIPDxAQEA8PDQ0PDw8PDw8PEBAPFREWFhUVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGC8iHSUtLSsrLS0rLS0rMC4rLTAtLS0rLSstLS0tLS0rLS0tLzUtLS0tLSstLS0tLS0tLS0rK//AABEIALcBEwMBIgACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAADBAACAQUGB//EAEkQAAIBAgIFBgoGCAYBBQAAAAECAAMRBCEFEjFBUQYTYXGBkQciMlKSobHB0fBCVHKT0uEWFyNDYoKj8RREU2Oy4lUVM0Vzg//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/EACgRAQACAQQBBAIBBQAAAAAAAAABAhEDEyFREjFBUmEUkQQiMkKBof/aAAwDAQACEQMRAD8A8vUQirIohVWBFWECyKsKqwMKsIqyyrCKsCqrCqksqQirAqqy4WXVYRUgUCS4SEVIQJAEElgkKElwkAISZCQ4SWCQF9SZ1IxqSakBbUk1IzqSakBXUmCkZ1JgpAVKShSNlJQpAUKShWNlIMpAUKyjLGmSDZYCrJBssaZYNlgKssEyxplg2WAqywTLGmWCZYC+rJCFZmBFWEVZFWFVYEVYVVmVWFVYGFWFVZlVhVWBhVhVSWRIVVgVVIRUl1SEVIFFSXCQqpCKkAQSXFOGCS4SAAU5YJGAksEgLakzqRnm5nm4CupMaka5uTm4ChSVKRwpKlICRpyhSOlINkgJMkoyRxkg2SAmywTJHGSCZICbLBsscZIFkgKMsEyxtlgmWAoywTLGmWCZYC1pIUrJAirCqswohkWBlFhVWRVhkWBFWGRZEWGVYGFWGVZlVhkSBVUhlSWVIZUgUVIRUnUaD0ErUi9UZ1B4o4Lxmv0loh6LcU3N8YyNWqQgpwqpCBIAAksKcOElwk","description":"bookbook","price":"100"}] \ No newline at end of file +[{"id":"1.1949186432461922","title":" wer ","imageUrl":" data:image/jpeg;base64,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 ","description":" ertfygh ","price":"54"},{"id":"1.6094309610182131","title":" asdfg ","imageUrl":" data:image/jpeg;base64,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 ","description":" ","price":"65"},{"id":"111","title":" sdg ","imageUrl":" data:image/jpeg;base64,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 ","description":" dfgnvh ","price":"5555"},{"id":"123","title":" asdf ","imageUrl":" data:image/jpeg;base64,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 ","description":" asdfgb ","price":"6352"}] \ No newline at end of file diff --git a/model/product.js b/model/product.js index 33893dc..b5aaa53 100644 --- a/model/product.js +++ b/model/product.js @@ -19,7 +19,6 @@ const getProductsFromFile = cb => { module.exports = class Product { constructor(id,title, imageUrl, description, price) { - // it will a null value here this.id = id; this.title = title; this.imageUrl = imageUrl; @@ -29,23 +28,15 @@ module.exports = class Product { save() { getProductsFromFile((products) => { - // if id is defined. tis will be true only if we are editing product if(this.id) { const existingProductIndex = products.findIndex(prods => prods.id === this.id); const updatedProduct = [...products]; - // "this" inside of this class is an updated product because we have imagined that we have created a new product instance. and we populate exisiting product by the newly created product instance. updatedProduct[existingProductIndex] = this; - // writing it to the file - // "updatedProduct" we have to save to the file as it contain edit product info fs.writeFile(p, JSON.stringify(updatedProduct), (err) => { - // console.log(err); - }); } else { - // if the productID is "null" ie, we are creating new product instance and not editing this.id = Math.random().toString(); - products.push(this); fs.writeFile(p, JSON.stringify(products), (err) => { @@ -56,6 +47,28 @@ module.exports = class Product { }); }; + static deleteById(id) { + // first of all we need to know which product to delete and then update rest of the products so that we can write back to the file + getProductsFromFile(products => { + // const productIndex = products.findIndex(prod => prod.id === id); + // now we get to know the index of product which we want to remove. and then afterwards removing, save rest of the products back to the file. + + // but,there is another function(inbuild), which will help us much better way + // "filter" also is anonymous function and will return all elements as part of new array that do match the condition + // const updatedProducts = products.filter(prods => prods.id === id); + + // but we only need elements whos id is not equal to the passed id so, + const updatedProducts = products.filter(prods => prods.id !== id); + + // saving to the file + fs.writeFile(p, JSON.stringify(updatedProducts), (err) => { + if(!err) { + // if no error occurs then we have to delete that element from that cart too, as if product doesnt exists then its no use of product to be in cart + } + }); + }); + }; + static fetchAll(cb) { getProductsFromFile(cb); }; diff --git a/routes/admin.js b/routes/admin.js index 6296017..480508d 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -14,5 +14,7 @@ routes.get('/edit-product/:productID', adminController.getEditProduct); routes.post('/edit-product', adminController.postEditProduct); +routes.post('/delete-product', adminController.postDeleteProduct); + routes.get('/products',adminController.getProducts) module.exports = routes; diff --git a/views/admin/products.ejs b/views/admin/products.ejs index e4569c4..0b8c3fb 100644 --- a/views/admin/products.ejs +++ b/views/admin/products.ejs @@ -31,6 +31,7 @@ Edit
    +
    From 8c6c876e7e12e8e5f7885a05790c36af22cb3e2a Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Fri, 17 Jan 2020 20:30:25 +0530 Subject: [PATCH 26/50] 125 Deleting Cart Items --- controller/admin.js | 3 ++ data/cart.json | 2 +- data/products.json | 2 +- model/cart.js | 80 +++++++++++++++++++-------------------------- model/product.js | 14 +++----- 5 files changed, 42 insertions(+), 59 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index 695583f..cc98123 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -53,6 +53,9 @@ exports.postEditProduct = (req, res, next) => { exports.postDeleteProduct = (req, res, next) => { const productID = req.body.productID; + // Product.deleteById(productID); + + // it will be better if we have callback to this, so that it should redirect, once it is done. Product.deleteById(productID); res.redirect('/admin/products'); }; diff --git a/data/cart.json b/data/cart.json index 4d88914..794ca83 100644 --- a/data/cart.json +++ b/data/cart.json @@ -1 +1 @@ -{"products":[{"id":"0.4961980477018628","qty":7},{"id":"0.49634733614067117","qty":1}],"totalPrice":45046} \ No newline at end of file +{"products":[],"totalPrice":null} \ No newline at end of file diff --git a/data/products.json b/data/products.json index 8a0bba5..456cc7f 100644 --- a/data/products.json +++ b/data/products.json @@ -1 +1 @@ -[{"id":"1.1949186432461922","title":" wer ","imageUrl":" data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8QDxIPDxAQEA8PDQ0PDw8PDw8PEBAPFREWFhUVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGC8iHSUtLSsrLS0rLS0rMC4rLTAtLS0rLSstLS0tLS0rLS0tLzUtLS0tLSstLS0tLS0tLS0rK//AABEIALcBEwMBIgACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAADBAACAQUGB//EAEkQAAIBAgIFBgoGCAYBBQAAAAECAAMRBCEFEjFBUQYTYXGBkQciMlKSobHB0fBCVHKT0uEWFyNDYoKj8RREU2Oy4lUVM0Vzg//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/EACgRAQACAQQBBAIBBQAAAAAAAAABAhEDEyFREjFBUmEUkQQiMkKBof/aAAwDAQACEQMRAD8A8vUQirIohVWBFWECyKsKqwMKsIqyyrCKsCqrCqksqQirAqqy4WXVYRUgUCS4SEVIQJAEElgkKElwkAISZCQ4SWCQF9SZ1IxqSakBbUk1IzqSakBXUmCkZ1JgpAVKShSNlJQpAUKShWNlIMpAUKyjLGmSDZYCrJBssaZYNlgKssEyxplg2WAqywTLGmWCZYC+rJCFZmBFWEVZFWFVYEVYVVmVWFVYGFWFVZlVhVWBhVhVSWRIVVgVVIRUl1SEVIFFSXCQqpCKkAQSXFOGCS4SAAU5YJGAksEgLakzqRnm5nm4CupMaka5uTm4ChSVKRwpKlICRpyhSOlINkgJMkoyRxkg2SAmywTJHGSCZICbLBsscZIFkgKMsEyxtlgmWAoywTLGmWCZYC1pIUrJAirCqswohkWBlFhVWRVhkWBFWGRZEWGVYGFWGVZlVhkSBVUhlSWVIZUgUVIRUnUaD0ErUi9UZ1B4o4Lxmv0loh6LcU3N8YyNWqQgpwqpCBIAAksKcOElwkBfm5ObjOpM6kBXm5Cka1JjUgKGnKlI4UlCkBMpBskdKQbJASZIJkjzJBMkBFkgmSOskE6QEWWCZY46QLLATdYFljjrAusBR1gWWNusC6wFtWSE1ZmBVRDosogh0ECyrDIsqiw6LAsiwyLMIsOiwMokMiSIsOiQIiTccn9F8/VzH7NLM548F7fdE8HhWqOqILsxsJ6DozALQpCmuZGbN5zHaYBQlsoDEUww1SLjeI42UXZe2TCuZ0hogr41PNd67xNeEnaFZrcdo5W8ZRZuG4wjQBJYU4waRBsRmJkJKF+bmebjISTUgLc3MGnGtSTUgKGnKFI4UlSkBJkg2SOskNhtHs/QvGBq6WGZzqqLmF0pos0QpJvrXv0GdZgMKlMWUZ8d8rpvCc5QYfSUa69Y/K8mVcCyQLpHmSBdJUIusA6R50gHWAi6wLrHHWAdYCbrAusbdYB1gLFZIQiSBVBDoJRBDosC6LDosogjCLAsixhFlUWMIsCyLDosqizY6KwjVaqIu9gTlcBRmSYHS8ltF82nPOPHceKD9FPiZ0FphCNky97ZSwAVDnnlnYbfZ7x27JRWB/t1QrL7Nmz1fO2U5vhtzy4G27o/OFVtBssKDllsy2X4ZDp+eMwyyDW4vDBs/pe2a/Um+qrEsTQ3jbINfqzOrDakzqSoBqzGrGNSQpAWKTHN3yEdp4Yt0DjHKGGC7NvGAlhtHja+fRNilLcBCrT3nZCWy4C3zeRQ1UDp49EKVlBnkMhuPHLd22hkGUuByentGhBrKLAH1HZ8JoHSehaQw4dCp+kCPhOFrUipKnIgkEdIkgIOkXdY86xd1lQjUWLusedYvUWAk6wDrG3WAcQFbSQhWSBRBDoIOmIwggEQRimsEgjNNYBUWMIsHTEYprALSS+W8zt9A6NFFNYj9o6i54DbaaHk3o/nKmuR4lPM9LbhOyJklYDrPYX9xPslcNj1J1WyuSFJIz+ffAYh77xwFs2E19Ubd195zPbOc3w1jLoWThsgynC3rHrmlwulmpmzXZOnyh0ze0aiVAHQ3Hztm6Xi3ozMTChS/Xnnlfjn8RBbP7kjYeiHZbStgfy93CbQBlgqiw7A7877+3ZaUYXmZUg6ZzGrD1ltJqxCAakPSw+890vSpxlE+eMKqqQir87pbs7L59smqT0WAyA7+rdLhGD3n537pnUzuTwsNo+cv7y6oNgG83y+c4QL35bZQIJxyGVhJWqqguxAEV0hpRKWQ8Z9w3DrM0Zq1KrazEm+zcoHQJx1NeteI5luKTLcLiecN9g3CaTlDhLOKg2OLH7Q/KbOgAguxA+dwimlsVr0yqjxbgknb2RS0z6loc06xeosedYtUWdWCNRYvUWO1Fi1QQEqixZxHagiziAsVmIQiSAKmIwggUEYQQD0xGaYgKYjVMQDUxGaYgaYm10RgjVqKLeJe7HoG34dsDqNCXp4dAQBca1gLbdl+mMVsfSHiu2rfje3fumKrTQY6oSSTv2DiOqcbXw6RDfAI/kOp6iIvXwreszka175EhrnMHMZ/O2SjpPEpktV+gMdb2zjOpHvDWHQVsOw7uv2wWHxNSg2svap2N1zXJynrjy0puBtJBUxqnyjw7ZVKb0zxHjj1Zznx6xKutwGkKdcZZMNqnaIdqc5ajzdTx8PVRmGd1azDrE3GC0kTZKw1W2Btx656dPXzxdi1OjpAtY/C+7b74Jltl6/yjTLv3WgGXd3T0S5l6yZdUGNwjDDKBw2ec55xw1gxTSXJtx6+nok+HXLIntvNwigS/XcdIv0Q6px7pYCw9pM1mK0tYlaQ123t9EfGZvqVpGbSsRM+jYYmulNdaowVemaHG6XqVfEogouzXPlHqG6anSemMPTa9etzlQfQTx2HYMlnPY7lVVe60FFBfOPjVPgJ5L6178RxH/XSKxDpqopURrVnAJzsTdj2RCpyivlRXUHnuASd2WfzacgFZm12Ys227azHtmxwyWyvl0g7e6ZpWIJl0mDrl82YsdtzNkq3FjvmkwCEMCOo57pu6U9EMtRXp2JHA2itRZt9JUtjccj1zWVBO7mSqLFagj1QRWoICVQRWoI7UEVqCAsRMS5EkANOMUxNgnJ3Efw+lDJoCv/AA98BOmIzTEbTQdbgvfDpoetwHfAXp7ukgDrM7bRWHWlTFyASN5tOX0bo5mxSq3k0gHbeNY5KPfNzpLFHW1beTsABM4a2p4ulatrWAOx17xEamAvtcdrCal8Qd4I62VYE1VP0b9tR55Z1pn2dfCGxfRlEeVVQdbQTYLC766d94mGG6kvaqj2mFUvuRB3e5ZnynpfGBTgcKf3yeuDfQ1FhZatM/zWmb1OKDv+Ex45+lS7f7SZ+jBZ+Tj7UIuNjI2YhKWKxdDxao56n/GCHHU0YQVdwpn7L2Pshhiqiizq1unxhJkw2ehtNo3ihiRvRsqidm8dU3hsQCMwcwROKqYelV8ZDzdQbGXj7ptNCaTZW5mvkdzbm6RO+jr+P9NvRi9M8w3b8YLCjxR0kn1xhxBYNfEU9F++emf7oc/YwqS9WoqDWY2HDeYHGYtKK6znPcJyOkMdUrk6xKr5q5NbpOxRMa38iNPiOZapp+XM+hvTPKEG6KC53U0P/JvdOexKY2uLE83T8xPEHaxzMbSoqjxbKP8AbAPe7Zd0Vr46nvKt1tUrHuFhPDmbTmeZdcY4gtT0Ei+VUpqd4Lr7oZNGUBtr0/SJgTpNR5NMn7OHUe0zP/q3+233KfGbzPSYgymAww/fp3tGKeDobq6ekZrjppd6d9Ee4yDTtPeq9tBh7DL526TxhvaOFp7qqHtWbClS4EHqInKrpuj/ALXosPbCppRD5LUh2fnNRrWj2Txjt0+IoFkI6LjrE0NQTOD0hU1wQ1Nlvnq3v7ZpdP4qph8cl2vQrbtwY/n7Z6dLV8o5Ymk54P1BFagj70idgi9TDv5pndza6oIrVE2NTCv5pi1TB1PNMDXmSMnBVfMMkDuFWEAmFEIomhAJXE1lpo1RzZUVmY9AF4UCIYxeerph9qU9XEYjgQD+yQ9bAm3BOmS04jLVYzIujg1Giarj9tVPOOD9Fm2L/KLCI1apJzOfT8I/pmrkFuozubn3b5pmqDZdmPBQVHcM583WmZth3r2MCP7KB6zI9ULmxVR/GxPqvABXbYpA6WCey7SyYQA3LIp/gUFvSa5nOKtZXXFqfIFR/sIFX0jaVOIbzKY/+yqXPcsOKCbwz/bLEdxy9UKjAbAi9RA9kuELKtVt6j7GH97Qi4d97t6FAe6G5z+IdgJmQ3S3o2gD5hvP9KnSPstMqXXep6i1M9xuITW6W9GY1ukdotIqpYN5Qs3G2q3waVdjYBjcA3VxtQwluIt6wZCnzxmZV0micXzlLxvKSwbp6YZcQtKgrtuppYcTaaDQ1bm6mqdjKw9WUxp/FFilFdiKt+u07xrTFPv0Y8Imfonjse9Z9Y3J3KNgEWanfy27AAbdQ2DtvCIlhYdttp64ZMM25bdJ2+ucIhqZK81T2lC54uWb1ZCFV7eTTA+yiiMDBk7WPYSPZaZOATfn1lj750xKZLGs/mt2BfhKNiiNocddO/ujZwFPgPXKnBKNlx1M3xjxlMkGxSHaafUygSj00O2mh6Rl7DH3wvTf7QBilTR67QoHShKn1RiV4I1MLQP0SvUfiIB9F0z5Ld4t6xHKmEYbHYdDAN69vrgHSqNqq3SCVPrvLmUxAWCwj0nuBccVN43yn0d/iMOSMnC6yneGHyIocTbylqL02LDvBmx0XjBU1qevr3W4BOY7DOlL84lPTmFeS2kf8RhlY+Wl6dQcHWbYicboyr/g9JvRawpYvNQNgqfR6icx2idpPdScwxq1xbj0nkJhBssORBsJpyAtMy9piBshCLKCEWBXEV1pozt5KKSbZk9A6Tsiujf2VMs41q9ZzVratiA5AAS+8KoVR9ma/TWODVloA+LT1atXgWz5tPUWPUsouKHGebW1OcQ7VriDVWmzMWO09Kj2TAoHdqj1wQxi+cO+Z/xyecveJ5sNjjDk7TLrh/4j2ZRU6SpDbUX0hKnTWHG2qnpCPE5PjDpCCkvCar9IcKP3q9mco3KjDD6RPZL4riW7CDhLBRwnPHlXQ3X9fwlf0spcP+f4Y8Twt06PUHCQ014Tm/0upcD2BvhMfpfR81+4yTX6a279T+nR8wvSOqY5kDYe+c+vK+ifouOsD4zNTlVQ1Sb2IBsCVBOR2Z9ERp54iCaXiMzDcVayIblgCLHbuvb3ytGzFiTcljfrnhvKjlNWxVYlHZaSnxNUst+m18o9yY5aVqBCVyXp7A21l2bejp2ztP8AGjHHq5+UZw9uRQNgmbmcVV8IWGyp0jzj82zs4B5tLbiTYnsmpxPK/E1L6mKw9PhalresvOO3Z0rSbRmHpRPTKGqo2sO8TynE6RxlT/5LsWkqj2ma6qmNb/PMenWZfYJuNP7Nq/xeynEJ5w7xMCsnnDvE8SqaOxZ/zZPXiKg90A2icUNlcnqrtNbcdszS8f4y911hxlGniVFNKU7FK1Ubv/fVh6zNnheUemKe0CqAbeMgY96xtdSzzHrD1ZoB6YPzacJQ5f11yr4N+umT7GAmzw/LvBtbX52kT/qU2A7xcTM6duky6CpQ4Xi6JqOHCrcb7WMHhtO4WqP2dem3QHF+6MGsDvBmMYVqeW+EFXDjEU8qlJgwa9itszlx2HsE32gNJDFYanW+ky2qAbqi5MO/PqIi61FsyG2q4sd9jxtOd5JVzhMZVwTmyVW1qW4a4GQHWuX8onq0rtTHlpzHvHP+vd3JlGlzKNPQ8ockkko2SwiiCWGWByuM5DirVescVUDVHLkaim3Abdwygv1eHdjKn3a/GdohhlMz4V6dd/U7cIfBw311/ul+MqfBq/11vuV+M9BUwgjbr0v5Gp8nnJ8GdT66fuF/FKnwY1frx+4X8U9LEsI269H5Gp8peYnwYV/r5+4H4pU+C7EfXz9wPjPUhLAS7dek/I1PlLyk+CzE/wDkP6H/AGlT4KsT/wCQ/o/9p6yBM2jbr0b+p8peRnwUYr6//SP4pU+CbFfX/wCm34p6/aZtG3XpN6/bxxvBHij/AJ4eg/4pV/BDiCuq2Ip1LEkEh0YX2553E9ltJaXbqb1+3iD+BvEbq1PtY/hg/wBTmL/1qXe3wnuVpLSbcG9PUfp4nQ8EmMS+rUo6zArrMzNYHbYACC/U3ifrFL0G+M9ytMWjbgnVtLw39T2K/wBel3MJj9UmMGyvT76gnuNpgrL4QzuWeH/qr0gNldPTqTB8GWkxsrU/Tb4T28rKlZNuGt23bxA+DnSo/e0j/P8A9ZX9ANMDY9H0/wAp7eUlSkm3Vd+/bxE8idND/RP/AOh+EjckNM2sUosOHO39ontZQShWNuq/kX7eJHkbpTfhqB/nT3iXpcmNKp5OHC/Yrgeq4ns5WDYSbcG/b6/Tyeno3TC/uGPXUpn3yuO0ZpSqabNhmV6JvTdSmsM7j6Wy89WYQDSbVVjXtHtH6I4bXKKXXVcqpdeDWzEyyxhhBPOjgBaZmZIQ0rQqvJJCiK0MrySQgqvLq8kkoIHlw8kkCwaWDSSSi2tM60kkDOtJrTMkCa0mtJJKjGtJrSSQJrSa0kkDGtMa0kkisFpUtJJAqWlS0kkChaULSSSAbNBM8zJAC7QLNJJIBM0C7SSQBFpJJIH/2Q== ","description":" ertfygh ","price":"54"},{"id":"1.6094309610182131","title":" asdfg ","imageUrl":" data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8QDxIPDxAQEA8PDQ0PDw8PDw8PEBAPFREWFhUVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGC8iHSUtLSsrLS0rLS0rMC4rLTAtLS0rLSstLS0tLS0rLS0tLzUtLS0tLSstLS0tLS0tLS0rK//AABEIALcBEwMBIgACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAADBAACAQUGB//EAEkQAAIBAgIFBgoGCAYBBQAAAAECAAMRBCEFEjFBUQYTYXGBkQciMlKSobHB0fBCVHKT0uEWFyNDYoKj8RREU2Oy4lUVM0Vzg//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/EACgRAQACAQQBBAIBBQAAAAAAAAABAhEDEyFREjFBUmEUkQQiMkKBof/aAAwDAQACEQMRAD8A8vUQirIohVWBFWECyKsKqwMKsIqyyrCKsCqrCqksqQirAqqy4WXVYRUgUCS4SEVIQJAEElgkKElwkAISZCQ4SWCQF9SZ1IxqSakBbUk1IzqSakBXUmCkZ1JgpAVKShSNlJQpAUKShWNlIMpAUKyjLGmSDZYCrJBssaZYNlgKssEyxplg2WAqywTLGmWCZYC+rJCFZmBFWEVZFWFVYEVYVVmVWFVYGFWFVZlVhVWBhVhVSWRIVVgVVIRUl1SEVIFFSXCQqpCKkAQSXFOGCS4SAAU5YJGAksEgLakzqRnm5nm4CupMaka5uTm4ChSVKRwpKlICRpyhSOlINkgJMkoyRxkg2SAmywTJHGSCZICbLBsscZIFkgKMsEyxtlgmWAoywTLGmWCZYC1pIUrJAirCqswohkWBlFhVWRVhkWBFWGRZEWGVYGFWGVZlVhkSBVUhlSWVIZUgUVIRUnUaD0ErUi9UZ1B4o4Lxmv0loh6LcU3N8YyNWqQgpwqpCBIAAksKcOElwkBfm5ObjOpM6kBXm5Cka1JjUgKGnKlI4UlCkBMpBskdKQbJASZIJkjzJBMkBFkgmSOskE6QEWWCZY46QLLATdYFljjrAusBR1gWWNusC6wFtWSE1ZmBVRDosogh0ECyrDIsqiw6LAsiwyLMIsOiwMokMiSIsOiQIiTccn9F8/VzH7NLM548F7fdE8HhWqOqILsxsJ6DozALQpCmuZGbN5zHaYBQlsoDEUww1SLjeI42UXZe2TCuZ0hogr41PNd67xNeEnaFZrcdo5W8ZRZuG4wjQBJYU4waRBsRmJkJKF+bmebjISTUgLc3MGnGtSTUgKGnKFI4UlSkBJkg2SOskNhtHs/QvGBq6WGZzqqLmF0pos0QpJvrXv0GdZgMKlMWUZ8d8rpvCc5QYfSUa69Y/K8mVcCyQLpHmSBdJUIusA6R50gHWAi6wLrHHWAdYCbrAusbdYB1gLFZIQiSBVBDoJRBDosC6LDosogjCLAsixhFlUWMIsCyLDosqizY6KwjVaqIu9gTlcBRmSYHS8ltF82nPOPHceKD9FPiZ0FphCNky97ZSwAVDnnlnYbfZ7x27JRWB/t1QrL7Nmz1fO2U5vhtzy4G27o/OFVtBssKDllsy2X4ZDp+eMwyyDW4vDBs/pe2a/Um+qrEsTQ3jbINfqzOrDakzqSoBqzGrGNSQpAWKTHN3yEdp4Yt0DjHKGGC7NvGAlhtHja+fRNilLcBCrT3nZCWy4C3zeRQ1UDp49EKVlBnkMhuPHLd22hkGUuByentGhBrKLAH1HZ8JoHSehaQw4dCp+kCPhOFrUipKnIgkEdIkgIOkXdY86xd1lQjUWLusedYvUWAk6wDrG3WAcQFbSQhWSBRBDoIOmIwggEQRimsEgjNNYBUWMIsHTEYprALSS+W8zt9A6NFFNYj9o6i54DbaaHk3o/nKmuR4lPM9LbhOyJklYDrPYX9xPslcNj1J1WyuSFJIz+ffAYh77xwFs2E19Ubd195zPbOc3w1jLoWThsgynC3rHrmlwulmpmzXZOnyh0ze0aiVAHQ3Hztm6Xi3ozMTChS/Xnnlfjn8RBbP7kjYeiHZbStgfy93CbQBlgqiw7A7877+3ZaUYXmZUg6ZzGrD1ltJqxCAakPSw+890vSpxlE+eMKqqQir87pbs7L59smqT0WAyA7+rdLhGD3n537pnUzuTwsNo+cv7y6oNgG83y+c4QL35bZQIJxyGVhJWqqguxAEV0hpRKWQ8Z9w3DrM0Zq1KrazEm+zcoHQJx1NeteI5luKTLcLiecN9g3CaTlDhLOKg2OLH7Q/KbOgAguxA+dwimlsVr0yqjxbgknb2RS0z6loc06xeosedYtUWdWCNRYvUWO1Fi1QQEqixZxHagiziAsVmIQiSAKmIwggUEYQQD0xGaYgKYjVMQDUxGaYgaYm10RgjVqKLeJe7HoG34dsDqNCXp4dAQBca1gLbdl+mMVsfSHiu2rfje3fumKrTQY6oSSTv2DiOqcbXw6RDfAI/kOp6iIvXwreszka175EhrnMHMZ/O2SjpPEpktV+gMdb2zjOpHvDWHQVsOw7uv2wWHxNSg2svap2N1zXJynrjy0puBtJBUxqnyjw7ZVKb0zxHjj1Zznx6xKutwGkKdcZZMNqnaIdqc5ajzdTx8PVRmGd1azDrE3GC0kTZKw1W2Btx656dPXzxdi1OjpAtY/C+7b74Jltl6/yjTLv3WgGXd3T0S5l6yZdUGNwjDDKBw2ec55xw1gxTSXJtx6+nok+HXLIntvNwigS/XcdIv0Q6px7pYCw9pM1mK0tYlaQ123t9EfGZvqVpGbSsRM+jYYmulNdaowVemaHG6XqVfEogouzXPlHqG6anSemMPTa9etzlQfQTx2HYMlnPY7lVVe60FFBfOPjVPgJ5L6178RxH/XSKxDpqopURrVnAJzsTdj2RCpyivlRXUHnuASd2WfzacgFZm12Ys227azHtmxwyWyvl0g7e6ZpWIJl0mDrl82YsdtzNkq3FjvmkwCEMCOo57pu6U9EMtRXp2JHA2itRZt9JUtjccj1zWVBO7mSqLFagj1QRWoICVQRWoI7UEVqCAsRMS5EkANOMUxNgnJ3Efw+lDJoCv/AA98BOmIzTEbTQdbgvfDpoetwHfAXp7ukgDrM7bRWHWlTFyASN5tOX0bo5mxSq3k0gHbeNY5KPfNzpLFHW1beTsABM4a2p4ulatrWAOx17xEamAvtcdrCal8Qd4I62VYE1VP0b9tR55Z1pn2dfCGxfRlEeVVQdbQTYLC766d94mGG6kvaqj2mFUvuRB3e5ZnynpfGBTgcKf3yeuDfQ1FhZatM/zWmb1OKDv+Ex45+lS7f7SZ+jBZ+Tj7UIuNjI2YhKWKxdDxao56n/GCHHU0YQVdwpn7L2Pshhiqiizq1unxhJkw2ehtNo3ihiRvRsqidm8dU3hsQCMwcwROKqYelV8ZDzdQbGXj7ptNCaTZW5mvkdzbm6RO+jr+P9NvRi9M8w3b8YLCjxR0kn1xhxBYNfEU9F++emf7oc/YwqS9WoqDWY2HDeYHGYtKK6znPcJyOkMdUrk6xKr5q5NbpOxRMa38iNPiOZapp+XM+hvTPKEG6KC53U0P/JvdOexKY2uLE83T8xPEHaxzMbSoqjxbKP8AbAPe7Zd0Vr46nvKt1tUrHuFhPDmbTmeZdcY4gtT0Ei+VUpqd4Lr7oZNGUBtr0/SJgTpNR5NMn7OHUe0zP/q3+233KfGbzPSYgymAww/fp3tGKeDobq6ekZrjppd6d9Ee4yDTtPeq9tBh7DL526TxhvaOFp7qqHtWbClS4EHqInKrpuj/ALXosPbCppRD5LUh2fnNRrWj2Txjt0+IoFkI6LjrE0NQTOD0hU1wQ1Nlvnq3v7ZpdP4qph8cl2vQrbtwY/n7Z6dLV8o5Ymk54P1BFagj70idgi9TDv5pndza6oIrVE2NTCv5pi1TB1PNMDXmSMnBVfMMkDuFWEAmFEIomhAJXE1lpo1RzZUVmY9AF4UCIYxeerph9qU9XEYjgQD+yQ9bAm3BOmS04jLVYzIujg1Giarj9tVPOOD9Fm2L/KLCI1apJzOfT8I/pmrkFuozubn3b5pmqDZdmPBQVHcM583WmZth3r2MCP7KB6zI9ULmxVR/GxPqvABXbYpA6WCey7SyYQA3LIp/gUFvSa5nOKtZXXFqfIFR/sIFX0jaVOIbzKY/+yqXPcsOKCbwz/bLEdxy9UKjAbAi9RA9kuELKtVt6j7GH97Qi4d97t6FAe6G5z+IdgJmQ3S3o2gD5hvP9KnSPstMqXXep6i1M9xuITW6W9GY1ukdotIqpYN5Qs3G2q3waVdjYBjcA3VxtQwluIt6wZCnzxmZV0micXzlLxvKSwbp6YZcQtKgrtuppYcTaaDQ1bm6mqdjKw9WUxp/FFilFdiKt+u07xrTFPv0Y8Imfonjse9Z9Y3J3KNgEWanfy27AAbdQ2DtvCIlhYdttp64ZMM25bdJ2+ucIhqZK81T2lC54uWb1ZCFV7eTTA+yiiMDBk7WPYSPZaZOATfn1lj750xKZLGs/mt2BfhKNiiNocddO/ujZwFPgPXKnBKNlx1M3xjxlMkGxSHaafUygSj00O2mh6Rl7DH3wvTf7QBilTR67QoHShKn1RiV4I1MLQP0SvUfiIB9F0z5Ld4t6xHKmEYbHYdDAN69vrgHSqNqq3SCVPrvLmUxAWCwj0nuBccVN43yn0d/iMOSMnC6yneGHyIocTbylqL02LDvBmx0XjBU1qevr3W4BOY7DOlL84lPTmFeS2kf8RhlY+Wl6dQcHWbYicboyr/g9JvRawpYvNQNgqfR6icx2idpPdScwxq1xbj0nkJhBssORBsJpyAtMy9piBshCLKCEWBXEV1pozt5KKSbZk9A6Tsiujf2VMs41q9ZzVratiA5AAS+8KoVR9ma/TWODVloA+LT1atXgWz5tPUWPUsouKHGebW1OcQ7VriDVWmzMWO09Kj2TAoHdqj1wQxi+cO+Z/xyecveJ5sNjjDk7TLrh/4j2ZRU6SpDbUX0hKnTWHG2qnpCPE5PjDpCCkvCar9IcKP3q9mco3KjDD6RPZL4riW7CDhLBRwnPHlXQ3X9fwlf0spcP+f4Y8Twt06PUHCQ014Tm/0upcD2BvhMfpfR81+4yTX6a279T+nR8wvSOqY5kDYe+c+vK+ifouOsD4zNTlVQ1Sb2IBsCVBOR2Z9ERp54iCaXiMzDcVayIblgCLHbuvb3ytGzFiTcljfrnhvKjlNWxVYlHZaSnxNUst+m18o9yY5aVqBCVyXp7A21l2bejp2ztP8AGjHHq5+UZw9uRQNgmbmcVV8IWGyp0jzj82zs4B5tLbiTYnsmpxPK/E1L6mKw9PhalresvOO3Z0rSbRmHpRPTKGqo2sO8TynE6RxlT/5LsWkqj2ma6qmNb/PMenWZfYJuNP7Nq/xeynEJ5w7xMCsnnDvE8SqaOxZ/zZPXiKg90A2icUNlcnqrtNbcdszS8f4y911hxlGniVFNKU7FK1Ubv/fVh6zNnheUemKe0CqAbeMgY96xtdSzzHrD1ZoB6YPzacJQ5f11yr4N+umT7GAmzw/LvBtbX52kT/qU2A7xcTM6duky6CpQ4Xi6JqOHCrcb7WMHhtO4WqP2dem3QHF+6MGsDvBmMYVqeW+EFXDjEU8qlJgwa9itszlx2HsE32gNJDFYanW+ky2qAbqi5MO/PqIi61FsyG2q4sd9jxtOd5JVzhMZVwTmyVW1qW4a4GQHWuX8onq0rtTHlpzHvHP+vd3JlGlzKNPQ8ockkko2SwiiCWGWByuM5DirVescVUDVHLkaim3Abdwygv1eHdjKn3a/GdohhlMz4V6dd/U7cIfBw311/ul+MqfBq/11vuV+M9BUwgjbr0v5Gp8nnJ8GdT66fuF/FKnwY1frx+4X8U9LEsI269H5Gp8peYnwYV/r5+4H4pU+C7EfXz9wPjPUhLAS7dek/I1PlLyk+CzE/wDkP6H/AGlT4KsT/wCQ/o/9p6yBM2jbr0b+p8peRnwUYr6//SP4pU+CbFfX/wCm34p6/aZtG3XpN6/bxxvBHij/AJ4eg/4pV/BDiCuq2Ip1LEkEh0YX2553E9ltJaXbqb1+3iD+BvEbq1PtY/hg/wBTmL/1qXe3wnuVpLSbcG9PUfp4nQ8EmMS+rUo6zArrMzNYHbYACC/U3ifrFL0G+M9ytMWjbgnVtLw39T2K/wBel3MJj9UmMGyvT76gnuNpgrL4QzuWeH/qr0gNldPTqTB8GWkxsrU/Tb4T28rKlZNuGt23bxA+DnSo/e0j/P8A9ZX9ANMDY9H0/wAp7eUlSkm3Vd+/bxE8idND/RP/AOh+EjckNM2sUosOHO39ontZQShWNuq/kX7eJHkbpTfhqB/nT3iXpcmNKp5OHC/Yrgeq4ns5WDYSbcG/b6/Tyeno3TC/uGPXUpn3yuO0ZpSqabNhmV6JvTdSmsM7j6Wy89WYQDSbVVjXtHtH6I4bXKKXXVcqpdeDWzEyyxhhBPOjgBaZmZIQ0rQqvJJCiK0MrySQgqvLq8kkoIHlw8kkCwaWDSSSi2tM60kkDOtJrTMkCa0mtJJKjGtJrSSQJrSa0kkDGtMa0kkisFpUtJJAqWlS0kkChaULSSSAbNBM8zJAC7QLNJJIBM0C7SSQBFpJJIH/2Q== ","description":" ","price":"65"},{"id":"111","title":" sdg ","imageUrl":" data:image/jpeg;base64,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 ","description":" dfgnvh ","price":"5555"},{"id":"123","title":" asdf ","imageUrl":" data:image/jpeg;base64,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 ","description":" asdfgb ","price":"6352"}] \ No newline at end of file +[{"id":"123","title":" asdf ","imageUrl":" data:image/jpeg;base64,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 ","description":" asdfgb ","price":"6352"}] \ No newline at end of file diff --git a/model/cart.js b/model/cart.js index f300c46..036ebec 100644 --- a/model/cart.js +++ b/model/cart.js @@ -1,77 +1,63 @@ -// our basic idea is to cart to hold all the objects we add and we want to group products by id and increade there quantity in case when we add producy more than once. - -// module.exports = class Cart{ -// constructor() { -// this.product = [], -// this.totalPrice = 0; -// } - -// // we to cart to add or remove products. but the problem we have is that cart itself is not a object, we will constently recreate. not for every new product that we add, we dont want to have a new cart, instaed there will be. -// // there will be always a cart in our app, we need to manage it -// } const fs = require('fs'); const path = require('path'); const rootDir = require('../util/path'); -const p = path.join(rootDir, 'data', 'cart.json'); +const p = path.join(rootDir, 'data', 'cart.json'); module.exports = class Cart { static addProduct(id, productPrice) { // fetch the previous product fs.readFile(p, (err, fileContent) => { - let cart = {products: [], totalPrice: 0}; - if(!err) { + let cart = { products: [], totalPrice: 0 }; + if (!err) { cart = JSON.parse(fileContent); } - // we will get all the products which are in cart - // console.log('cart : ' ,cart); - - // // analysing the cart => finding existing product - // const exisitingProduct = cart.products.find(prod => prod.id === id); - // let updatedProduct; - - // // add new product / incraese the quantity - // if(exisitingProduct) { - // updatedProduct = {...exisitingProduct}; - // updatedProduct.qty = updatedProduct.qty + 1; - // // here also, we have to update the product in the cart. as product is already present here, we need to find the index where it is located - // } else { - // updatedProduct = {id: id, qty: 1}; - // // updating the cart after adding new product to the cart - // cart.products = [...cart.products, updatedProduct]; - // } - - // cart.totalPrice = cart.totalPrice + productPrice; - - - // analysing the cart => finding existing product const exisitingProductIndex = cart.products.findIndex(prod => prod.id === id); const exisitingProduct = cart.products[exisitingProductIndex]; let updatedProduct; // add new product / incraese the quantity - if(exisitingProduct) { - updatedProduct = {...exisitingProduct}; + if (exisitingProduct) { + updatedProduct = { ...exisitingProduct }; updatedProduct.qty = updatedProduct.qty + 1; - // here also, we have to update the product in the cart. as product is already present here, we need to find the index where it is located cart.products = [...cart.products]; cart.products[exisitingProductIndex] = updatedProduct; } else { - updatedProduct = {id: id, qty: 1}; + updatedProduct = { id: id, qty: 1 }; // updating the cart after adding new product to the cart - cart.products = [...cart.products, updatedProduct]; + cart.products = [...cart.products, updatedProduct]; } - - // productPrice is acting as a string here, to convert into number type, we are adding "+" operator before varible name cart.totalPrice = cart.totalPrice + +productPrice; - - // writeing down the changes to file fs.writeFile(p, JSON.stringify(cart), err => { console.log(err); }); - }); + } + static deleteProduct(id, productPrice) { + fs.readFile(p, (err, fileContent) => { + if (err) { + // if there is nothing in cart, we can get a error as there is nothing to delete. + // so we will return the cart as it is + return; + } + // if no error occurs, then we will delete the product from the cart and reduce the total price + // we are in readFile(), so instead of accessing "cart", we have to access "fileContent" which contain all cart products + // fileContent is in JSON formate, so we have convert it back to the JS formate + const updatedProduct = { ...JSON.parse(fileContent) }; + const product = updatedProduct.products.find(prods => prods.id === id); + const productQty = product.qty; + updatedProduct.products = updatedProduct.products.filter(prods => prods.id !== id); + // const updatedTotalPrice = product.totalPrice - (productPrice * productQty); + updatedProduct.totalPrice = updatedProduct - (productPrice * productQty); + + // once everything is updated after deleting, storing it back to the file + fs.writeFile(p, JSON.stringify(updatedProduct), (err) => { + console.log(err); + }); + }); } -} \ No newline at end of file + +} + diff --git a/model/product.js b/model/product.js index b5aaa53..dfa5b13 100644 --- a/model/product.js +++ b/model/product.js @@ -2,6 +2,7 @@ const fs = require('fs'); const path = require('path'); const rootDir = require('../util/path'); +const Cart = require('./cart'); const p = path.join(rootDir, 'data', 'products.json'); @@ -48,22 +49,15 @@ module.exports = class Product { }; static deleteById(id) { - // first of all we need to know which product to delete and then update rest of the products so that we can write back to the file getProductsFromFile(products => { - // const productIndex = products.findIndex(prod => prod.id === id); - // now we get to know the index of product which we want to remove. and then afterwards removing, save rest of the products back to the file. - - // but,there is another function(inbuild), which will help us much better way - // "filter" also is anonymous function and will return all elements as part of new array that do match the condition - // const updatedProducts = products.filter(prods => prods.id === id); - - // but we only need elements whos id is not equal to the passed id so, + const updatedProducts = products.filter(prods => prods.id !== id); + const productPrice = (products.find(prods => prods.id === id)).price; - // saving to the file fs.writeFile(p, JSON.stringify(updatedProducts), (err) => { if(!err) { // if no error occurs then we have to delete that element from that cart too, as if product doesnt exists then its no use of product to be in cart + Cart.deleteProduct(id, productPrice); } }); }); From 59913c8de80738a745e901b1c7de816ee793386c Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Fri, 17 Jan 2020 21:52:36 +0530 Subject: [PATCH 27/50] 126 Displaying Cart Items on the Cart Page --- controller/shop.js | 32 +++++++++++++++++++++++++++++--- data/cart.json | 2 +- data/products.json | 2 +- model/cart.js | 25 ++++++++++++++++++------- notes.txt | 12 +++++++++++- views/shop/cart.ejs | 26 ++++++++++++++++++++++---- 6 files changed, 82 insertions(+), 17 deletions(-) diff --git a/controller/shop.js b/controller/shop.js index 2115113..abba78b 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -21,10 +21,36 @@ exports.getDetails = (req, res, next) => { }; exports.getCart = (req, res, next) => { - res.render('shop/cart', { - pageTitle: 'Cart', - path: '/cart' + // passing a callback function, once successful, it will get an cart items + Cart.getCart(cart => { + // along with the cart, we need product details like title. as cart is only having an product id and quantity. + // so, to get thr product details + Product.fetchAll(products => { + // now from fetchAll method, we will get all the products. if have to find which products are in cart. thus going through all the products + const cartProducts = []; + for(product of products) { + // thus checking if present product is in cart + // if(cart.products.find(prod => prod.id === product.id)) { + // // if the product is in cart, then add it to "cartProduts" array + // cartProducts.push(product); + // // but along with product details, we need quantity of product too. quantity is strord in cart, hence we need to extract that too. + // } + const CartproductData = cart.products.find(prod => prod.id === product.id) + if(CartproductData) { + cartProducts.push({productData: product, qty: CartproductData.qty}); + // thus, we have product details and quantity of a product + } + } + res.render('shop/cart', { + pageTitle: 'Cart', + path: '/cart', + // cartProducts is an array which is having both product details and porduct quantity + products: cartProducts + }); + }); + }); + }; exports.postCart = (req, res, next) => { diff --git a/data/cart.json b/data/cart.json index 794ca83..805726c 100644 --- a/data/cart.json +++ b/data/cart.json @@ -1 +1 @@ -{"products":[],"totalPrice":null} \ No newline at end of file +{"products":[{"id":"123","qty":6},{"id":"0.5016805059353091","qty":3}],"totalPrice":38145} \ No newline at end of file diff --git a/data/products.json b/data/products.json index 456cc7f..b4c175b 100644 --- a/data/products.json +++ b/data/products.json @@ -1 +1 @@ -[{"id":"123","title":" asdf ","imageUrl":" data:image/jpeg;base64,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 ","description":" asdfgb ","price":"6352"}] \ No newline at end of file +[{"id":"123","title":" asdf ","imageUrl":" data:image/jpeg;base64,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 ","description":" asdfgb ","price":"6352"},{"id":"0.5016805059353091","title":"dfgh","imageUrl":" data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8QDxIPDxAQEA8PDQ0PDw8PDw8PEBAPFREWFhUVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGC8iHSUtLSsrLS0rLS0rMC4rLTAtLS0rLSstLS0tLS0rLS0tLzUtLS0tLSstLS0tLS0tLS0rK//AABEIALcBEwMBIgACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAADBAACAQUGB//EAEkQAAIBAgIFBgoGCAYBBQAAAAECAAMRBCEFEjFBUQYTYXGBkQciMlKSobHB0fBCVHKT0uEWFyNDYoKj8RREU2Oy4lUVM0Vzg//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/EACgRAQACAQQBBAIBBQAAAAAAAAABAhEDEyFREjFBUmEUkQQiMkKBof/aAAwDAQACEQMRAD8A8vUQirIohVWBFWECyKsKqwMKsIqyyrCKsCqrCqksqQirAqqy4WXVYRUgUCS4SEVIQJAEElgkKElwkAISZCQ4SWCQF9SZ1IxqSakBbUk1IzqSakBXUmCkZ1JgpAVKShSNlJQpAUKShWNlIMpAUKyjLGmSDZYCrJBssaZYNlgKssEyxplg2WAqywTLGmWCZYC+rJCFZmBFWEVZFWFVYEVYVVmVWFVYGFWFVZlVhVWBhVhVSWRIVVgVVIRUl1SEVIFFSXCQqpCKkAQSXFOGCS4SAAU5YJGAksEgLakzqRnm5nm4CupMaka5uTm4ChSVKRwpKlICRpyhSOlINkgJMkoyRxkg2SAmywTJHGSCZICbLBsscZIFkgKMsEyxtlgmWAoywTLGmWCZYC1pIUrJAirCqswohkWBlFhVWRVhkWBFWGRZEWGVYGFWGVZlVhkSBVUhlSWVIZUgUVIRUnUaD0ErUi9UZ1B4o4Lxmv0loh6LcU3N8YyNWqQgpwqpCBIAAksKcOElwk","description":"sdfgh","price":"11"}] \ No newline at end of file diff --git a/model/cart.js b/model/cart.js index 036ebec..c3d63fc 100644 --- a/model/cart.js +++ b/model/cart.js @@ -38,26 +38,37 @@ module.exports = class Cart { static deleteProduct(id, productPrice) { fs.readFile(p, (err, fileContent) => { if (err) { - // if there is nothing in cart, we can get a error as there is nothing to delete. - // so we will return the cart as it is return; } - // if no error occurs, then we will delete the product from the cart and reduce the total price - // we are in readFile(), so instead of accessing "cart", we have to access "fileContent" which contain all cart products - // fileContent is in JSON formate, so we have convert it back to the JS formate const updatedProduct = { ...JSON.parse(fileContent) }; const product = updatedProduct.products.find(prods => prods.id === id); const productQty = product.qty; updatedProduct.products = updatedProduct.products.filter(prods => prods.id !== id); - // const updatedTotalPrice = product.totalPrice - (productPrice * productQty); updatedProduct.totalPrice = updatedProduct - (productPrice * productQty); - // once everything is updated after deleting, storing it back to the file fs.writeFile(p, JSON.stringify(updatedProduct), (err) => { console.log(err); }); }); } + // we will return the entire cart in the callback + // we add a callback so that we can call it once we get all the id's which are present in cart + static getCart(cb) { + fs.readFile(p, (err, fileContent) => { + // converting JSON to JS data + const cart = JSON.parse(fileContent); + // this will fail, if we got an error, thus checking for error + // cb(cart); + + if(err) { + // if no items are present in the cart + cb(null); + } else { + cb(cart); + } + }); + } + } diff --git a/notes.txt b/notes.txt index a33758e..4b254eb 100644 --- a/notes.txt +++ b/notes.txt @@ -48,4 +48,14 @@ html syntax is different but if we inspect page, it will shows us proper html co <%= renderingDynamicValue %> <%} %> ---> \ No newline at end of file +--> + +
      + + <% products.forEach(p => { %> + + + +
    • <%= p.productData.title %> (<%= p.qty %>)
    • + <% }) %> +
    \ No newline at end of file diff --git a/views/shop/cart.ejs b/views/shop/cart.ejs index aac0373..8716469 100644 --- a/views/shop/cart.ejs +++ b/views/shop/cart.ejs @@ -1,6 +1,24 @@ <%- include('../includes/head.ejs') %> - + - - <%- include('../includes/navigation.ejs') %> - <%- include('../includes/end.ejs') %> \ No newline at end of file + +<%- include('../includes/navigation.ejs') %> +
    + <% if (products.length > 0 ) { %> +
      + + <% products.forEach(p => { %> + + + +
    • <%= p.productData.title %> (<%= p.qty %>)
    • + <% }) %> +
    + <% } else { %> +

    No Cart Products!!

    + <% } %> + +
    + + +<%- include('../includes/end.ejs') %> \ No newline at end of file From 19f1f18417a6057101a8886f3531e3d217ced614 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Fri, 17 Jan 2020 22:32:07 +0530 Subject: [PATCH 28/50] 127 Deleting Cart Items --- controller/shop.js | 28 +++++++++++++--------------- data/cart.json | 2 +- data/products.json | 2 +- routes/shop.js | 2 ++ views/shop/cart.ejs | 12 +++++++----- 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/controller/shop.js b/controller/shop.js index abba78b..15f87e1 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -13,7 +13,6 @@ exports.getProduct = (req, res, next) => { exports.getDetails = (req, res, next) => { const productID = req.params.productId; - // console.log(productID); Product.findById(productID, product => { res.render('shop/product-detail', { pageTitle: product.title, product: product, path: '/products' }); }); @@ -21,30 +20,18 @@ exports.getDetails = (req, res, next) => { }; exports.getCart = (req, res, next) => { - // passing a callback function, once successful, it will get an cart items Cart.getCart(cart => { - // along with the cart, we need product details like title. as cart is only having an product id and quantity. - // so, to get thr product details Product.fetchAll(products => { - // now from fetchAll method, we will get all the products. if have to find which products are in cart. thus going through all the products const cartProducts = []; for(product of products) { - // thus checking if present product is in cart - // if(cart.products.find(prod => prod.id === product.id)) { - // // if the product is in cart, then add it to "cartProduts" array - // cartProducts.push(product); - // // but along with product details, we need quantity of product too. quantity is strord in cart, hence we need to extract that too. - // } const CartproductData = cart.products.find(prod => prod.id === product.id) if(CartproductData) { cartProducts.push({productData: product, qty: CartproductData.qty}); - // thus, we have product details and quantity of a product } } res.render('shop/cart', { pageTitle: 'Cart', path: '/cart', - // cartProducts is an array which is having both product details and porduct quantity products: cartProducts }); }); @@ -54,8 +41,6 @@ exports.getCart = (req, res, next) => { }; exports.postCart = (req, res, next) => { - // as request was "POST", so it contains the productID as agrument within the url of "form" - // "productID" is the name given to the value ID, in the form field. const productID = req.body.productID console.log(productID); Product.findById(productID, product => { @@ -64,6 +49,19 @@ exports.postCart = (req, res, next) => { res.redirect('/'); } +exports.postCartDeleteProduct = (req, res, next) => { + // while deleting, we have delete product only from the cart and not product as a whole from everywhere + // getting the productID which we get it from post request while deleting the item + const productID = req.body.productID; + // finding the product + Product.findById(productID, product => { + // after getting the product, we will get to know the product price, which can be sent to cart to delete an item. + // we can even directly send product price along with productID from the form. but its a good practice.thus using " Product.findById" method to extract product details + Cart.deleteProduct(productID, product.price); + res.redirect('/cart'); + }); +}; + exports.getOrders = (req, res, next) => { res.render('shop/orders', { pageTitle: 'Orders', diff --git a/data/cart.json b/data/cart.json index 805726c..794ca83 100644 --- a/data/cart.json +++ b/data/cart.json @@ -1 +1 @@ -{"products":[{"id":"123","qty":6},{"id":"0.5016805059353091","qty":3}],"totalPrice":38145} \ No newline at end of file +{"products":[],"totalPrice":null} \ No newline at end of file diff --git a/data/products.json b/data/products.json index b4c175b..0637a08 100644 --- a/data/products.json +++ b/data/products.json @@ -1 +1 @@ -[{"id":"123","title":" asdf ","imageUrl":" data:image/jpeg;base64,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 ","description":" asdfgb ","price":"6352"},{"id":"0.5016805059353091","title":"dfgh","imageUrl":" data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8QDxIPDxAQEA8PDQ0PDw8PDw8PEBAPFREWFhUVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGC8iHSUtLSsrLS0rLS0rMC4rLTAtLS0rLSstLS0tLS0rLS0tLzUtLS0tLSstLS0tLS0tLS0rK//AABEIALcBEwMBIgACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAADBAACAQUGB//EAEkQAAIBAgIFBgoGCAYBBQAAAAECAAMRBCEFEjFBUQYTYXGBkQciMlKSobHB0fBCVHKT0uEWFyNDYoKj8RREU2Oy4lUVM0Vzg//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/EACgRAQACAQQBBAIBBQAAAAAAAAABAhEDEyFREjFBUmEUkQQiMkKBof/aAAwDAQACEQMRAD8A8vUQirIohVWBFWECyKsKqwMKsIqyyrCKsCqrCqksqQirAqqy4WXVYRUgUCS4SEVIQJAEElgkKElwkAISZCQ4SWCQF9SZ1IxqSakBbUk1IzqSakBXUmCkZ1JgpAVKShSNlJQpAUKShWNlIMpAUKyjLGmSDZYCrJBssaZYNlgKssEyxplg2WAqywTLGmWCZYC+rJCFZmBFWEVZFWFVYEVYVVmVWFVYGFWFVZlVhVWBhVhVSWRIVVgVVIRUl1SEVIFFSXCQqpCKkAQSXFOGCS4SAAU5YJGAksEgLakzqRnm5nm4CupMaka5uTm4ChSVKRwpKlICRpyhSOlINkgJMkoyRxkg2SAmywTJHGSCZICbLBsscZIFkgKMsEyxtlgmWAoywTLGmWCZYC1pIUrJAirCqswohkWBlFhVWRVhkWBFWGRZEWGVYGFWGVZlVhkSBVUhlSWVIZUgUVIRUnUaD0ErUi9UZ1B4o4Lxmv0loh6LcU3N8YyNWqQgpwqpCBIAAksKcOElwk","description":"sdfgh","price":"11"}] \ No newline at end of file +[] \ No newline at end of file diff --git a/routes/shop.js b/routes/shop.js index 5da53da..c6dd55f 100644 --- a/routes/shop.js +++ b/routes/shop.js @@ -16,6 +16,8 @@ routes.get('/cart', shopController.getCart); routes.post('/cart', shopController.postCart); +routes.post('/cart-delete-item', shopController.postCartDeleteProduct); + routes.get('/orders', shopController.getOrders); module.exports = routes; diff --git a/views/shop/cart.ejs b/views/shop/cart.ejs index 8716469..656412b 100644 --- a/views/shop/cart.ejs +++ b/views/shop/cart.ejs @@ -6,12 +6,14 @@
    <% if (products.length > 0 ) { %>
      - <% products.forEach(p => { %> - - - -
    • <%= p.productData.title %> (<%= p.qty %>)
    • +
    • +

      <%= p.productData.title %> (<%= p.qty %>)

      +
      + + +
      +
    • <% }) %>
    <% } else { %> From 0ab1ea4f44f7828ec5fe15a817ca568714836534 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Fri, 17 Jan 2020 22:48:28 +0530 Subject: [PATCH 29/50] 128 Fixing a Delete Product Bug --- data/products.json | 2 +- model/cart.js | 12 +++++------- model/product.js | 1 - 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/data/products.json b/data/products.json index 0637a08..6f49935 100644 --- a/data/products.json +++ b/data/products.json @@ -1 +1 @@ -[] \ No newline at end of file +[{"id":"0.21217683817981658","title":"book","imageUrl":" data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8QDxIPDxAQEA8PDQ0PDw8PDw8PEBAPFREWFhUVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGC8iHSUtLSsrLS0rLS0rMC4rLTAtLS0rLSstLS0tLS0rLS0tLzUtLS0tLSstLS0tLS0tLS0rK//AABEIALcBEwMBIgACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAADBAACAQUGB//EAEkQAAIBAgIFBgoGCAYBBQAAAAECAAMRBCEFEjFBUQYTYXGBkQciMlKSobHB0fBCVHKT0uEWFyNDYoKj8RREU2Oy4lUVM0Vzg//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/EACgRAQACAQQBBAIBBQAAAAAAAAABAhEDEyFREjFBUmEUkQQiMkKBof/aAAwDAQACEQMRAD8A8vUQirIohVWBFWECyKsKqwMKsIqyyrCKsCqrCqksqQirAqqy4WXVYRUgUCS4SEVIQJAEElgkKElwkAISZCQ4SWCQF9SZ1IxqSakBbUk1IzqSakBXUmCkZ1JgpAVKShSNlJQpAUKShWNlIMpAUKyjLGmSDZYCrJBssaZYNlgKssEyxplg2WAqywTLGmWCZYC+rJCFZmBFWEVZFWFVYEVYVVmVWFVYGFWFVZlVhVWBhVhVSWRIVVgVVIRUl1SEVIFFSXCQqpCKkAQSXFOGCS4SAAU5YJGAksEgLakzqRnm5nm4CupMaka5uTm4ChSVKRwpKlICRpyhSOlINkgJMkoyRxkg2SAmywTJHGSCZICbLBsscZIFkgKMsEyxtlgmWAoywTLGmWCZYC1pIUrJAirCqswohkWBlFhVWRVhkWBFWGRZEWGVYGFWGVZlVhkSBVUhlSWVIZUgUVIRUnUaD0ErUi9UZ1B4o4Lxmv0loh6LcU3N8YyNWqQgpwqpCBIAAksKcOElwk","description":"1","price":"11"}] \ No newline at end of file diff --git a/model/cart.js b/model/cart.js index c3d63fc..6a69aaf 100644 --- a/model/cart.js +++ b/model/cart.js @@ -42,6 +42,11 @@ module.exports = class Cart { } const updatedProduct = { ...JSON.parse(fileContent) }; const product = updatedProduct.products.find(prods => prods.id === id); + // if we delete a product from admin page and that product is not inn the cart, then it will give us error. + // SOLUTION:- to delete, we first need to check if the given product is in cart, if it is not there then we simply need to return . we dont want to try to edit it as it is not there. + if(!product) { + return; + } const productQty = product.qty; updatedProduct.products = updatedProduct.products.filter(prods => prods.id !== id); updatedProduct.totalPrice = updatedProduct - (productPrice * productQty); @@ -52,17 +57,10 @@ module.exports = class Cart { }); } - // we will return the entire cart in the callback - // we add a callback so that we can call it once we get all the id's which are present in cart static getCart(cb) { fs.readFile(p, (err, fileContent) => { - // converting JSON to JS data const cart = JSON.parse(fileContent); - // this will fail, if we got an error, thus checking for error - // cb(cart); - if(err) { - // if no items are present in the cart cb(null); } else { cb(cart); diff --git a/model/product.js b/model/product.js index dfa5b13..3f739df 100644 --- a/model/product.js +++ b/model/product.js @@ -56,7 +56,6 @@ module.exports = class Product { fs.writeFile(p, JSON.stringify(updatedProducts), (err) => { if(!err) { - // if no error occurs then we have to delete that element from that cart too, as if product doesnt exists then its no use of product to be in cart Cart.deleteProduct(id, productPrice); } }); From 3a894d8cde7fd2d2d8087df1b593a4a8a37c4340 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Sat, 18 Jan 2020 22:32:40 +0530 Subject: [PATCH 30/50] 136 Connecting our App to the SQL Database --- app.js | 12 +++++++++ notes.txt | 65 ++++-------------------------------------------- package.json | 1 + util/database.js | 27 ++++++++++++++++++++ util/notes.txt | 4 --- 5 files changed, 45 insertions(+), 64 deletions(-) create mode 100644 util/database.js delete mode 100644 util/notes.txt diff --git a/app.js b/app.js index a99b7ef..20d6890 100644 --- a/app.js +++ b/app.js @@ -7,6 +7,7 @@ const adminRoutes = require('./routes/admin'); const shopRoutes = require('./routes/shop'); const rootDir = require('./util/path'); const errorController = require('./controller/error'); +const db = require('./util/database'); const app = express(); @@ -16,6 +17,17 @@ app.set('views', 'views'); app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static(path.join(rootDir, 'public'))); +// EG: using the connection pool, +// both commands will execute query but execute is bit safer +// db.execute() db.query() +// we have to end our connection also when our appliaction shuts down +// db.end(); +// but we will not shut our appliaction down. + +// within execute('') we can write down our sql command +// creating the table 'products' tabel in our database and writing down entries +db.execute('SELECT * FROM products'); + app.use('/admin', adminRoutes); app.use(shopRoutes); diff --git a/notes.txt b/notes.txt index 4b254eb..a4af5f0 100644 --- a/notes.txt +++ b/notes.txt @@ -1,61 +1,6 @@ -express js is all about middleware -ie, incoming request will passthrough bunch of functions -thus, there will be more than request handler. - it helps in code segreation +10.136 +installing mysql : +npm install --save mysql2 - - -we can have same url for more then one webpage till the time method ccessing that webpages are different -eg: /admin/add-products => GET - /admin/add-products => POST - routes.get('/add-products', (req, res, next) => { - routes.post('/add-products', (req, res, next) => { - - - -res.sendFile('/views/addProducts.html'); -this will cause error, as node will check for a file from root directory of and not from -root directory of the project -thus, "path" module will be used to specify the path to html files. - - - - -this will not work as node will not allow us to acces us the internal files on the browser -ie, localhost:300/public/css/main.css - -to access these static files, we have to modify our main app.js file -we need to serve files statically and stically simply means that its not handles by -router or expressjs or any other middleware. -but should be directly forwarded to file sysytem - - -installing templating engines -npm install --save ejs pug express-handlebars - - -pug: -html syntax is different but if we inspect page, it will shows us proper html code - - - - - -
      - - <% products.forEach(p => { %> - - - -
    • <%= p.productData.title %> (<%= p.qty %>)
    • - <% }) %> -
    \ No newline at end of file +util/database.js +app.js \ No newline at end of file diff --git a/package.json b/package.json index 03b305b..321834f 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "ejs": "^3.0.1", "express": "^4.17.1", "express-handlebars": "^3.1.0", + "mysql2": "^2.1.0", "pug": "^2.0.4" } } diff --git a/util/database.js b/util/database.js new file mode 100644 index 0000000..911ec7f --- /dev/null +++ b/util/database.js @@ -0,0 +1,27 @@ +// we have set the connection between our app and sql database. so we can pass queries from our app and get the results from the database. + +const mysql = require('mysql2'); + +// we have 2 ways of connecting to database +// 1. we set up connection which we can use to run queries and we should always close the connection once we are done with the query. DOWNSIDE: we need to re-execute the code to create the connection for every new query and there will be lot of queries because we will fetch data, delete data, write data. so creating a new connections all the times becomes inefficient both in our code and also regarding the connection to the database which is establish and the performance this may cost. + // mysql.createConnection + +// 2. create a connection pool (can read in documents of mysql2) +// creating pool of connections which will always reach out to it whenever we have query to run and then we get new connection from that pool which manage multiple connections so that we can run multiple queries simultaneously because earch query needs its own connection and once query is done, connecttion will be handed back to the pool and its avaliable for new query. pool will be finished once our application finishes/shuts down. +// const pool = mysql.createPool() + +// we need to pass JS object within it with some info about our database engine with whom we are connecting. +const pool = mysql.createPool({ + // passing server name/ip address + host: 'localhost', + // passing username, by default username is root while configering database + user: 'root', + // passing database name as database will have multiple schemas within it + database: 'nodeapp', + // passing password of database + password: 'toor' +}); + +// after creating a pool, we can export it +// we are exporting it in different way ie with promise() method. as this will allow us to use promises when working with pool connections which handles asynchronous data. we are not using callbacks, because promises allow us to write code in bit more structured way.[ no need of nested callabcks but we can have promise chain] +module.exports = pool.promise(); \ No newline at end of file diff --git a/util/notes.txt b/util/notes.txt deleted file mode 100644 index 48340ca..0000000 --- a/util/notes.txt +++ /dev/null @@ -1,4 +0,0 @@ -util folder is nothing but a helper folder -it means that it contains a helper file ie, it will help other files - -path.js file is helping other js files in setting up path more easilt and efficently From 30b15ffa1ad8346fd63d292b407d4779e3880171 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Sat, 18 Jan 2020 22:56:22 +0530 Subject: [PATCH 31/50] 137 Basic SQL Creating a Table --- app.js | 13 +++---------- notes.txt | 7 ++++++- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/app.js b/app.js index 20d6890..ecdb521 100644 --- a/app.js +++ b/app.js @@ -17,16 +17,9 @@ app.set('views', 'views'); app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static(path.join(rootDir, 'public'))); -// EG: using the connection pool, -// both commands will execute query but execute is bit safer -// db.execute() db.query() -// we have to end our connection also when our appliaction shuts down -// db.end(); -// but we will not shut our appliaction down. - -// within execute('') we can write down our sql command -// creating the table 'products' tabel in our database and writing down entries -db.execute('SELECT * FROM products'); +// as we have exported promises along with pool from "database.js". +// so when we execute queries, we will get promise which contain the response +db.execute('SELECT * FROM products').then().cath(); app.use('/admin', adminRoutes); app.use(shopRoutes); diff --git a/notes.txt b/notes.txt index a4af5f0..0c0a476 100644 --- a/notes.txt +++ b/notes.txt @@ -3,4 +3,9 @@ installing mysql : npm install --save mysql2 util/database.js -app.js \ No newline at end of file +app.js + +10.137 +add the item in product table of database +app.js +https://dictionary.cambridge.org/images/full/book_noun_001_01679.jpg?version=5.0.65 From 0a63447962cfdd03dd896f70123645b7fe542e3d Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Sat, 18 Jan 2020 23:13:58 +0530 Subject: [PATCH 32/50] 138 Retrieving Data --- app.js | 25 ++++++++++++++++++++++--- util/database.js | 2 +- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index ecdb521..78a063d 100644 --- a/app.js +++ b/app.js @@ -17,9 +17,28 @@ app.set('views', 'views'); app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static(path.join(rootDir, 'public'))); -// as we have exported promises along with pool from "database.js". -// so when we execute queries, we will get promise which contain the response -db.execute('SELECT * FROM products').then().cath(); +// if we will not use promise, then we have to use callback +// EG: db.execute('SELECT * FROM products', cb => {}) + +// promises helps us to write cleaner code and gives us then() nad catch() block. both the blocks will take anomous function and will execute one of them according to the condition +// .then() when request is successful +// .cath() in case of error +// db.execute('SELECT * FROM products') +// .then((result) => { +// console.log(result); +// }) +// .catch(err => console.log(err)); + + // .then will be executes and gives us an array which has 2 sub arrays + // first array is the result from database and second array hold the metadata + +// thus extrating seprately +db.execute('SELECT * FROM products') + .then((result) => { + console.log(result[0]); + console.log(result[1]); + }) + .catch(err => console.log(err)); app.use('/admin', adminRoutes); app.use(shopRoutes); diff --git a/util/database.js b/util/database.js index 911ec7f..0034556 100644 --- a/util/database.js +++ b/util/database.js @@ -19,7 +19,7 @@ const pool = mysql.createPool({ // passing database name as database will have multiple schemas within it database: 'nodeapp', // passing password of database - password: 'toor' + password: 'root' }); // after creating a pool, we can export it From 6c059d573b81f46af9fc53c0ed88bf62c1efa6af Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Sun, 19 Jan 2020 11:57:43 +0530 Subject: [PATCH 33/50] 140 Fetching Products - Time to Practice --- app.js | 12 ++--- controller/shop.js | 48 ++++++++++------- model/product.js | 131 +++++++++++++++++++++++++++++---------------- notes.txt | 37 +++++++++---- 4 files changed, 147 insertions(+), 81 deletions(-) diff --git a/app.js b/app.js index 78a063d..08d8e64 100644 --- a/app.js +++ b/app.js @@ -33,12 +33,12 @@ app.use(express.static(path.join(rootDir, 'public'))); // first array is the result from database and second array hold the metadata // thus extrating seprately -db.execute('SELECT * FROM products') - .then((result) => { - console.log(result[0]); - console.log(result[1]); - }) - .catch(err => console.log(err)); +// db.execute('SELECT * FROM products') +// .then((result) => { +// console.log(result[0]); +// console.log(result[1]); +// }) +// .catch(err => console.log(err)); app.use('/admin', adminRoutes); app.use(shopRoutes); diff --git a/controller/shop.js b/controller/shop.js index 15f87e1..cffc421 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -2,13 +2,16 @@ const Product = require('../model/product'); const Cart = require('../model/cart'); exports.getProduct = (req, res, next) => { - Product.fetchAll((products) => { - res.render("shop/product-list", { - pageTitle: "Shop Products", - prods: products, - path: "/products" - }); - }) + Product.fetchAll() + .then(([rows, fieldsData]) => { + console.log(rows); + res.render("shop/product-list", { + pageTitle: "Shop Products", + prods: rows, + path: "/products" + }); + }) + .catch(err => console.log(err)); }; exports.getDetails = (req, res, next) => { @@ -50,13 +53,8 @@ exports.postCart = (req, res, next) => { } exports.postCartDeleteProduct = (req, res, next) => { - // while deleting, we have delete product only from the cart and not product as a whole from everywhere - // getting the productID which we get it from post request while deleting the item const productID = req.body.productID; - // finding the product Product.findById(productID, product => { - // after getting the product, we will get to know the product price, which can be sent to cart to delete an item. - // we can even directly send product price along with productID from the form. but its a good practice.thus using " Product.findById" method to extract product details Cart.deleteProduct(productID, product.price); res.redirect('/cart'); }); @@ -69,14 +67,26 @@ exports.getOrders = (req, res, next) => { }); }; +// using the same approach as used in getProduct() exports.getIndex = (req, res, next) => { - Product.fetchAll((products) => { - res.render("shop/index", { - pageTitle: "Shop", - prods: products, - path: "/" - }); - }) + // Product.fetchAll((products) => { + // res.render("shop/index", { + // pageTitle: "Shop", + // prods: products, + // path: "/" + // }); + // }) + + Product.fetchAll() + // we only need first sub array so we can only destructure by provinding only one value, which will take first sub array + .then(([rows]) => { + res.render("shop/index", { + pageTitle: "Shop", + prods: rows, + path: "/" + }); + }) + .catch (err => console.log(err)); }; diff --git a/model/product.js b/model/product.js index 3f739df..02d9f94 100644 --- a/model/product.js +++ b/model/product.js @@ -1,20 +1,22 @@ -const fs = require('fs'); -const path = require('path'); +/************************************************************* -const rootDir = require('../util/path'); +// const fs = require('fs'); +// const path = require('path'); + +// const rootDir = require('../util/path'); const Cart = require('./cart'); -const p = path.join(rootDir, 'data', 'products.json'); +// const p = path.join(rootDir, 'data', 'products.json'); -const getProductsFromFile = cb => { - fs.readFile(p, (err, fileContent) => { - if(err) { - cb([]); - } else { - cb(JSON.parse(fileContent)); - } - }); -} +// const getProductsFromFile = cb => { +// fs.readFile(p, (err, fileContent) => { +// if(err) { +// cb([]); +// } else { +// cb(JSON.parse(fileContent)); +// } +// }); +// } module.exports = class Product { @@ -28,48 +30,83 @@ module.exports = class Product { } save() { - getProductsFromFile((products) => { - if(this.id) { - const existingProductIndex = products.findIndex(prods => prods.id === this.id); - const updatedProduct = [...products]; - updatedProduct[existingProductIndex] = this; - - fs.writeFile(p, JSON.stringify(updatedProduct), (err) => { - }); - } else { - this.id = Math.random().toString(); - products.push(this); + // getProductsFromFile((products) => { + // if(this.id) { + // const existingProductIndex = products.findIndex(prods => prods.id === this.id); + // const updatedProduct = [...products]; + // updatedProduct[existingProductIndex] = this; + + // fs.writeFile(p, JSON.stringify(updatedProduct), (err) => { + // }); + // } else { + // this.id = Math.random().toString(); + // products.push(this); - fs.writeFile(p, JSON.stringify(products), (err) => { - console.log(err); - }); - } + // fs.writeFile(p, JSON.stringify(products), (err) => { + // console.log(err); + // }); + // } - }); + // }); }; static deleteById(id) { - getProductsFromFile(products => { + // getProductsFromFile(products => { - const updatedProducts = products.filter(prods => prods.id !== id); - const productPrice = (products.find(prods => prods.id === id)).price; - - fs.writeFile(p, JSON.stringify(updatedProducts), (err) => { - if(!err) { - Cart.deleteProduct(id, productPrice); - } - }); - }); + // const updatedProducts = products.filter(prods => prods.id !== id); + // const productPrice = (products.find(prods => prods.id === id)).price; + + // fs.writeFile(p, JSON.stringify(updatedProducts), (err) => { + // if(!err) { + // Cart.deleteProduct(id, productPrice); + // } + // }); + // }); }; - static fetchAll(cb) { - getProductsFromFile(cb); + static fetchAll() { + // getProductsFromFile(cb); }; - static findById(id, cb) { - getProductsFromFile(products => { - const product = products.find(p => p.id === id); - cb(product); - }); + static findById(id) { + // getProductsFromFile(products => { + // const product = products.find(p => p.id === id); + // cb(product); + // }); + // }; +}; + + +***********************************************************************/ + +const db = require('../util/database'); + +const Cart = require('./cart'); + +module.exports = class Product { + + constructor(id,title, imageUrl, description, price) { + this.id = id; + this.title = title; + this.imageUrl = imageUrl; + this.description = description; + this.price = price; + } + + save() { + }; -}; \ No newline at end of file + + static deleteById(id) { + + }; + + static fetchAll() { + return db.execute('SELECT * FROM products'); + }; + + static findById(id) { + } +}; + + diff --git a/notes.txt b/notes.txt index 0c0a476..b49b249 100644 --- a/notes.txt +++ b/notes.txt @@ -1,11 +1,30 @@ -10.136 -installing mysql : -npm install --save mysql2 -util/database.js -app.js +10.139 +model/product +controller/shop + + +10.140 +controller/shop + + + + + + + + + + + + + + + + + + + + + -10.137 -add the item in product table of database -app.js -https://dictionary.cambridge.org/images/full/book_noun_001_01679.jpg?version=5.0.65 From 6ee5c3b7dd1434ac5447194e49b5f828aa13fd04 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Sun, 19 Jan 2020 13:03:13 +0530 Subject: [PATCH 34/50] 141 Inserting Data Into the Database --- controller/admin.js | 8 +++- controller/shop.js | 10 ----- model/product.js | 93 +++++---------------------------------------- notes.txt | 9 ++--- 4 files changed, 19 insertions(+), 101 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index cc98123..dccd1e0 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -17,8 +17,12 @@ exports.postAddProduct = (req, res, next) => { // passing null value in id parameter of constructor of a class const product = new Product(null, title, imageUrl, description, price); - product.save(); - res.redirect("/"); + product.save() + .then(() => { + // as we are inserting, we dont need agruments + res.redirect("/"); + }) + .catch(err => console.log(err)); }; exports.getEditProduct = (req, res, next) => { diff --git a/controller/shop.js b/controller/shop.js index cffc421..c839884 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -67,18 +67,8 @@ exports.getOrders = (req, res, next) => { }); }; -// using the same approach as used in getProduct() exports.getIndex = (req, res, next) => { - // Product.fetchAll((products) => { - // res.render("shop/index", { - // pageTitle: "Shop", - // prods: products, - // path: "/" - // }); - // }) - Product.fetchAll() - // we only need first sub array so we can only destructure by provinding only one value, which will take first sub array .then(([rows]) => { res.render("shop/index", { pageTitle: "Shop", diff --git a/model/product.js b/model/product.js index 02d9f94..306a2a0 100644 --- a/model/product.js +++ b/model/product.js @@ -1,91 +1,10 @@ -/************************************************************* - -// const fs = require('fs'); -// const path = require('path'); - -// const rootDir = require('../util/path'); -const Cart = require('./cart'); - -// const p = path.join(rootDir, 'data', 'products.json'); - -// const getProductsFromFile = cb => { -// fs.readFile(p, (err, fileContent) => { -// if(err) { -// cb([]); -// } else { -// cb(JSON.parse(fileContent)); -// } -// }); -// } - - -module.exports = class Product { - - constructor(id,title, imageUrl, description, price) { - this.id = id; - this.title = title; - this.imageUrl = imageUrl; - this.description = description; - this.price = price; - } - - save() { - // getProductsFromFile((products) => { - // if(this.id) { - // const existingProductIndex = products.findIndex(prods => prods.id === this.id); - // const updatedProduct = [...products]; - // updatedProduct[existingProductIndex] = this; - - // fs.writeFile(p, JSON.stringify(updatedProduct), (err) => { - // }); - // } else { - // this.id = Math.random().toString(); - // products.push(this); - - // fs.writeFile(p, JSON.stringify(products), (err) => { - // console.log(err); - // }); - // } - - // }); - }; - - static deleteById(id) { - // getProductsFromFile(products => { - - // const updatedProducts = products.filter(prods => prods.id !== id); - // const productPrice = (products.find(prods => prods.id === id)).price; - - // fs.writeFile(p, JSON.stringify(updatedProducts), (err) => { - // if(!err) { - // Cart.deleteProduct(id, productPrice); - // } - // }); - // }); - }; - - static fetchAll() { - // getProductsFromFile(cb); - }; - - static findById(id) { - // getProductsFromFile(products => { - // const product = products.find(p => p.id === id); - // cb(product); - // }); - // }; -}; - - -***********************************************************************/ - const db = require('../util/database'); const Cart = require('./cart'); module.exports = class Product { - - constructor(id,title, imageUrl, description, price) { + + constructor(id, title, imageUrl, description, price) { this.id = id; this.title = title; this.imageUrl = imageUrl; @@ -94,7 +13,13 @@ module.exports = class Product { } save() { - + // to prevent sql injection (attack in which user enter code instaed of data which can be used to hack the database), we will put "?" instaed of directly putting values. + // thus, second argument will take the values and put them as data inplace of "?". + // this is extra security feature + // "title, imageUrl, price, description" should have the same names of the fields in table 'products' + // db.execute() is a method which will give out promise. so we will return it to the fuction which is calling this function. hence using "return" + return db.execute('INSERT INTO products(title, imageUrl, price, description) VALUES (?,?,?,?)', + [this.title, this.imageUrl, this.price, this.description]); }; static deleteById(id) { diff --git a/notes.txt b/notes.txt index b49b249..a064fbb 100644 --- a/notes.txt +++ b/notes.txt @@ -1,12 +1,11 @@ -10.139 -model/product -controller/shop - - 10.140 controller/shop +10.141 +model/product.js +controller/admin.js + From 2a6ca7f30670fabf48c14cdbba532c2ca8e8d5e5 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Sun, 19 Jan 2020 13:36:11 +0530 Subject: [PATCH 35/50] 142 Fetching a Single Product with the where Condition --- controller/admin.js | 28 ++++++++++++++------ controller/shop.js | 62 +++++++++++++++++++++++++++------------------ model/product.js | 6 +---- notes.txt | 3 ++- 4 files changed, 61 insertions(+), 38 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index dccd1e0..c52dc1c 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -32,14 +32,26 @@ exports.getEditProduct = (req, res, next) => { } const productID = req.params.productID; - Product.findById(productID, product => { - res.render("admin/edit-product", { - path: "/admin/edit-product", - pageTitle: "Edit Products", - editing: editMode, - product: product - }); - }); + // Product.findById(productID, product => { + // res.render("admin/edit-product", { + // path: "/admin/edit-product", + // pageTitle: "Edit Products", + // editing: editMode, + // product: product + // }); + // }); + + // done in advance + Product.findById(productID) + .then(([row]) => { + res.render("admin/edit-product", { + path: "/admin/edit-product", + pageTitle: "Edit Products", + editing: editMode, + product: row + }); + }) + .catch(err => console.log(err)); }; diff --git a/controller/shop.js b/controller/shop.js index c839884..3b456f7 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -3,23 +3,39 @@ const Cart = require('../model/cart'); exports.getProduct = (req, res, next) => { Product.fetchAll() - .then(([rows, fieldsData]) => { - console.log(rows); - res.render("shop/product-list", { - pageTitle: "Shop Products", - prods: rows, - path: "/products" - }); - }) - .catch(err => console.log(err)); + .then(([rows, fieldsData]) => { + console.log(rows); + res.render("shop/product-list", { + pageTitle: "Shop Products", + prods: rows, + path: "/products" + }); + }) + .catch(err => console.log(err)); }; exports.getDetails = (req, res, next) => { const productID = req.params.productId; - Product.findById(productID, product => { - res.render('shop/product-detail', { pageTitle: product.title, product: product, path: '/products' }); - }); + // Product.findById(productID, product => { + // res.render('shop/product-detail', { pageTitle: product.title, product: product, path: '/products' }); + // }); + Product.findById(productID) + .then(([product]) => { + console.log(product); + res.render( + 'shop/product-detail', + { pageTitle: product.title, + // it will give us error, as we are passing an array but according to setup, we have to pass the array. + // within the array, we got our product which we need at first index. + // product: product, + // so, sepicify the object index + product: product[0], + path: '/products' + } + ); + }) + .catch(err => console.log(err)); }; exports.getCart = (req, res, next) => { @@ -37,10 +53,8 @@ exports.getCart = (req, res, next) => { path: '/cart', products: cartProducts }); - }); - - }); - + }); + }); }; exports.postCart = (req, res, next) => { @@ -69,14 +83,14 @@ exports.getOrders = (req, res, next) => { exports.getIndex = (req, res, next) => { Product.fetchAll() - .then(([rows]) => { - res.render("shop/index", { - pageTitle: "Shop", - prods: rows, - path: "/" - }); - }) - .catch (err => console.log(err)); + .then(([rows]) => { + res.render("shop/index", { + pageTitle: "Shop", + prods: rows, + path: "/" + }); + }) + .catch (err => console.log(err)); }; diff --git a/model/product.js b/model/product.js index 306a2a0..ed0920c 100644 --- a/model/product.js +++ b/model/product.js @@ -13,11 +13,6 @@ module.exports = class Product { } save() { - // to prevent sql injection (attack in which user enter code instaed of data which can be used to hack the database), we will put "?" instaed of directly putting values. - // thus, second argument will take the values and put them as data inplace of "?". - // this is extra security feature - // "title, imageUrl, price, description" should have the same names of the fields in table 'products' - // db.execute() is a method which will give out promise. so we will return it to the fuction which is calling this function. hence using "return" return db.execute('INSERT INTO products(title, imageUrl, price, description) VALUES (?,?,?,?)', [this.title, this.imageUrl, this.price, this.description]); }; @@ -31,6 +26,7 @@ module.exports = class Product { }; static findById(id) { + return db.execute('SELECT * FROM products WHERE products.id = ?', [id]); } }; diff --git a/notes.txt b/notes.txt index a064fbb..62bc64b 100644 --- a/notes.txt +++ b/notes.txt @@ -6,7 +6,8 @@ controller/shop model/product.js controller/admin.js - +10.142 +model/products.js From 4d3fc6fd96f9285cfc6568ee4965d9e87895957e Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Sun, 19 Jan 2020 20:19:28 +0530 Subject: [PATCH 36/50] 147 Connecting to the Database --- controller/admin.js | 1 - controller/shop.js | 4 --- notes.txt | 14 +++++----- package.json | 3 ++- util/database.js | 63 +++++++++++++++++++++++++++------------------ util/path.js | 13 +--------- 6 files changed, 48 insertions(+), 50 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index c52dc1c..9c56e6d 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -19,7 +19,6 @@ exports.postAddProduct = (req, res, next) => { product.save() .then(() => { - // as we are inserting, we dont need agruments res.redirect("/"); }) .catch(err => console.log(err)); diff --git a/controller/shop.js b/controller/shop.js index 3b456f7..08071d7 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -26,10 +26,6 @@ exports.getDetails = (req, res, next) => { res.render( 'shop/product-detail', { pageTitle: product.title, - // it will give us error, as we are passing an array but according to setup, we have to pass the array. - // within the array, we got our product which we need at first index. - // product: product, - // so, sepicify the object index product: product[0], path: '/products' } diff --git a/notes.txt b/notes.txt index 62bc64b..9fe9144 100644 --- a/notes.txt +++ b/notes.txt @@ -1,13 +1,13 @@ -10.140 -controller/shop +11.147 +npm install --save sequelize +to work with sequelize, u should install "mysql2" +npm install --save mysql2 +util/database.js + + -10.141 -model/product.js -controller/admin.js -10.142 -model/products.js diff --git a/package.json b/package.json index 321834f..72d3c19 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "express": "^4.17.1", "express-handlebars": "^3.1.0", "mysql2": "^2.1.0", - "pug": "^2.0.4" + "pug": "^2.0.4", + "sequelize": "^5.21.3" } } diff --git a/util/database.js b/util/database.js index 0034556..f30ba93 100644 --- a/util/database.js +++ b/util/database.js @@ -1,27 +1,40 @@ -// we have set the connection between our app and sql database. so we can pass queries from our app and get the results from the database. - -const mysql = require('mysql2'); - -// we have 2 ways of connecting to database -// 1. we set up connection which we can use to run queries and we should always close the connection once we are done with the query. DOWNSIDE: we need to re-execute the code to create the connection for every new query and there will be lot of queries because we will fetch data, delete data, write data. so creating a new connections all the times becomes inefficient both in our code and also regarding the connection to the database which is establish and the performance this may cost. - // mysql.createConnection - -// 2. create a connection pool (can read in documents of mysql2) -// creating pool of connections which will always reach out to it whenever we have query to run and then we get new connection from that pool which manage multiple connections so that we can run multiple queries simultaneously because earch query needs its own connection and once query is done, connecttion will be handed back to the pool and its avaliable for new query. pool will be finished once our application finishes/shuts down. -// const pool = mysql.createPool() - -// we need to pass JS object within it with some info about our database engine with whom we are connecting. -const pool = mysql.createPool({ - // passing server name/ip address - host: 'localhost', - // passing username, by default username is root while configering database - user: 'root', - // passing database name as database will have multiple schemas within it - database: 'nodeapp', - // passing password of database - password: 'root' +// const mysql = require('mysql2'); + +// const pool = mysql.createPool({ +// host: 'localhost', +// user: 'root', +// database: 'nodeapp', +// password: 'root' +// }); + +// module.exports = pool.promise(); + + + + +// first step is to craete a model with sequlize and connect with database +// deleting other tables in database if there (because we want sequlize to manage our tables) +// connecting to database +// even though we are not importing mysql but it uses mysql behind the sceans + +const Sequelize = require('sequelize'); +// "Sequelize" is constructor function... its a class + +// creating the new instance of Sequelize +// Sequelize() accepts numbers of paramerters username, password,database, password +// 1: database name +// 2: username +// 3. password +// 4: option objects {} +// dialect: tells which database we are using . this is nessary as different sql databases have littel different sql syntax +// host: by default it will use localhost, but we set explicitly +const sequelize = new Sequelize('nodeapp', 'root', 'root', { + dialect: 'mysql', + host: 'localhost' }); -// after creating a pool, we can export it -// we are exporting it in different way ie with promise() method. as this will allow us to use promises when working with pool connections which handles asynchronous data. we are not using callbacks, because promises allow us to write code in bit more structured way.[ no need of nested callabcks but we can have promise chain] -module.exports = pool.promise(); \ No newline at end of file +// thus, this will create connection pool with sequelize object +module.exports = sequelize; + + + diff --git a/util/path.js b/util/path.js index f6cff62..df0c281 100644 --- a/util/path.js +++ b/util/path.js @@ -1,14 +1,3 @@ const path = require('path'); -// "dirname" : Return the directory name of a path -// so, we have to find out for which dirfile, we have to get the name -// "process" : its a global variable, present in all the files -// it contains the mainModule property -// "mainModule" : tells the main module which started our application -// "filename": to get the filename where main module file started the application - -// "(process.mainModule.filename)" it gives us the name of main application which started all the process ie "app.js" - -// dirname(process.mainModule.filename) : it will gives the path of "app.js" file where it is located. - -module.exports = path.dirname(process.mainModule.filename) \ No newline at end of file +module.exports = path.dirname(process.mainModule.filename); \ No newline at end of file From 92218a0c6c2a463fcacba3f8edf94377e9e1e114 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Sun, 19 Jan 2020 20:47:27 +0530 Subject: [PATCH 37/50] 148 Defining a Model --- model/product.js | 42 ++++++++++++++++++++++++++++++++++++++++++ notes.txt | 3 +++ 2 files changed, 45 insertions(+) diff --git a/model/product.js b/model/product.js index ed0920c..eda6b24 100644 --- a/model/product.js +++ b/model/product.js @@ -1,3 +1,5 @@ +/************************************************************** + const db = require('../util/database'); const Cart = require('./cart'); @@ -30,4 +32,44 @@ module.exports = class Product { } }; +******************************************************************/ +// we will recreate our product model from scratch + +// importing sequelize class +const Sequelize = require('sequelize'); + +// importing sequelize object +const sequelize = require('../util/database'); +// it is not only a connection pool but is fully configured sequelize environment which does have a connection pool but have other features of sequelize package .active + +// defining our new model by "define()" which takes some arguments +// 1st: modelName - it is typically in lowercase +// 2nd: define the structure of our model, which will automatically create database tabel. this will be JS object and in this we define the attributes or fields our tabel should have +const Product = sequelize.define('product', { + // here defining the attrivutes wgich table should have + id : { + // defining the properties if "id" field + type: Sequelize.INTEGER, + allowNull : false, + autoIncrement : true, + primaryKey : true + }, + // if we have to define only type of attribute it should be, we can do it in one line without creating object + title : Sequelize.STRING, + price : { + type: Sequelize.DOUBLE, + allowNull: false + }, + imageUrl : { + type: Sequelize.STRING, + allowNull: false + }, + description : { + type : Sequelize.STRING, + allowNull: false + } +}); + +// now we have set up our model and its ready to be used +module.exports = Product; diff --git a/notes.txt b/notes.txt index 9fe9144..bb3c1f6 100644 --- a/notes.txt +++ b/notes.txt @@ -5,6 +5,9 @@ to work with sequelize, u should install "mysql2" npm install --save mysql2 util/database.js +11.148 +model/products.js + From 6fa0064164cadbfd370d14ec8e878d4a68a297d7 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Sun, 19 Jan 2020 21:15:35 +0530 Subject: [PATCH 38/50] 149 Syncing JS Definitions to the Database --- app.js | 49 ++++++++++++++++++++++++------------------------ model/product.js | 14 +------------- notes.txt | 9 ++------- 3 files changed, 27 insertions(+), 45 deletions(-) diff --git a/app.js b/app.js index 08d8e64..d6e1e45 100644 --- a/app.js +++ b/app.js @@ -7,7 +7,8 @@ const adminRoutes = require('./routes/admin'); const shopRoutes = require('./routes/shop'); const rootDir = require('./util/path'); const errorController = require('./controller/error'); -const db = require('./util/database'); +// const db = require('./util/database'); +const sequelize = require('./util/database'); const app = express(); @@ -17,32 +18,30 @@ app.set('views', 'views'); app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static(path.join(rootDir, 'public'))); -// if we will not use promise, then we have to use callback -// EG: db.execute('SELECT * FROM products', cb => {}) - -// promises helps us to write cleaner code and gives us then() nad catch() block. both the blocks will take anomous function and will execute one of them according to the condition -// .then() when request is successful -// .cath() in case of error -// db.execute('SELECT * FROM products') -// .then((result) => { -// console.log(result); -// }) -// .catch(err => console.log(err)); - - // .then will be executes and gives us an array which has 2 sub arrays - // first array is the result from database and second array hold the metadata - -// thus extrating seprately -// db.execute('SELECT * FROM products') -// .then((result) => { -// console.log(result[0]); -// console.log(result[1]); -// }) -// .catch(err => console.log(err)); - app.use('/admin', adminRoutes); app.use(shopRoutes); app.use(errorController.get404); -app.listen(3000); \ No newline at end of file + +// now our models are created, we have to tell sequelize to create table in database as specified. +// if tables are already present, it should not override it. but if we want, we can tell dequelize to do so + +// there is a special method, sync method +// sync method have to look all the methdos, we define (products model in products.js). so its aware of all the models and then create tables for them +// sequelize.sync(); +// thus, it syncs all the models to the db(database) by creating appropiate tables and relations, if we have defined +// sequelize will give promise + +sequelize.sync() +.then(result => { + console.log('result' ,result); + // if sync is successfull, then server should start + app.listen(3000); +}) +.catch(err => { + console.log('err', err); +}) + +// thus, if promise is successful, it will create a tabel 'products' eventhough we specified 'product' in our model. +// along with those fields it will also create 2 from fields by default ie, createdAt and updatedAt. if we dont want, we can tell sequelized not to make. \ No newline at end of file diff --git a/model/product.js b/model/product.js index eda6b24..b4f9780 100644 --- a/model/product.js +++ b/model/product.js @@ -32,30 +32,19 @@ module.exports = class Product { } }; -******************************************************************/ +*****************************************************************/ -// we will recreate our product model from scratch - -// importing sequelize class const Sequelize = require('sequelize'); -// importing sequelize object const sequelize = require('../util/database'); -// it is not only a connection pool but is fully configured sequelize environment which does have a connection pool but have other features of sequelize package .active -// defining our new model by "define()" which takes some arguments -// 1st: modelName - it is typically in lowercase -// 2nd: define the structure of our model, which will automatically create database tabel. this will be JS object and in this we define the attributes or fields our tabel should have const Product = sequelize.define('product', { - // here defining the attrivutes wgich table should have id : { - // defining the properties if "id" field type: Sequelize.INTEGER, allowNull : false, autoIncrement : true, primaryKey : true }, - // if we have to define only type of attribute it should be, we can do it in one line without creating object title : Sequelize.STRING, price : { type: Sequelize.DOUBLE, @@ -71,5 +60,4 @@ const Product = sequelize.define('product', { } }); -// now we have set up our model and its ready to be used module.exports = Product; diff --git a/notes.txt b/notes.txt index bb3c1f6..51eccf3 100644 --- a/notes.txt +++ b/notes.txt @@ -1,14 +1,9 @@ -11.147 -npm install --save sequelize -to work with sequelize, u should install "mysql2" -npm install --save mysql2 -util/database.js - 11.148 model/products.js - +11.149 +app.js From f9a0181104abc16ab678420b65edbc5eb919c1ae Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Sun, 19 Jan 2020 21:59:41 +0530 Subject: [PATCH 39/50] 150 Inserting Data Creating a Product --- app.js | 19 ++----------------- controller/admin.js | 39 ++++++++++++++++++++++++++++++++------- model/product.js | 36 ------------------------------------ notes.txt | 3 ++- util/database.js | 33 ++++----------------------------- 5 files changed, 40 insertions(+), 90 deletions(-) diff --git a/app.js b/app.js index d6e1e45..87646b3 100644 --- a/app.js +++ b/app.js @@ -7,7 +7,6 @@ const adminRoutes = require('./routes/admin'); const shopRoutes = require('./routes/shop'); const rootDir = require('./util/path'); const errorController = require('./controller/error'); -// const db = require('./util/database'); const sequelize = require('./util/database'); const app = express(); @@ -23,25 +22,11 @@ app.use(shopRoutes); app.use(errorController.get404); - -// now our models are created, we have to tell sequelize to create table in database as specified. -// if tables are already present, it should not override it. but if we want, we can tell dequelize to do so - -// there is a special method, sync method -// sync method have to look all the methdos, we define (products model in products.js). so its aware of all the models and then create tables for them -// sequelize.sync(); -// thus, it syncs all the models to the db(database) by creating appropiate tables and relations, if we have defined -// sequelize will give promise - sequelize.sync() .then(result => { - console.log('result' ,result); - // if sync is successfull, then server should start + // console.log('result' ,result); app.listen(3000); }) .catch(err => { console.log('err', err); -}) - -// thus, if promise is successful, it will create a tabel 'products' eventhough we specified 'product' in our model. -// along with those fields it will also create 2 from fields by default ie, createdAt and updatedAt. if we dont want, we can tell sequelized not to make. \ No newline at end of file +}); \ No newline at end of file diff --git a/controller/admin.js b/controller/admin.js index 9c56e6d..b3597f9 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -14,14 +14,39 @@ exports.postAddProduct = (req, res, next) => { const description = req.body.description; const price = req.body.price; - // passing null value in id parameter of constructor of a class - const product = new Product(null, title, imageUrl, description, price); + // const product = new Product(null, title, imageUrl, description, price); - product.save() - .then(() => { - res.redirect("/"); - }) - .catch(err => console.log(err)); + // product.save() + // .then(() => { + // res.redirect("/"); + // }) + // .catch(err => console.log(err)); + + + // as we are using sequlize, we will add product by help of sequlize + + // "create()" creates a new element based on the model and immmeditely saves it to db. so, first we get object in JS first then it gets saved automatiavlly. + // "build()" also creates new object based on the model but only in JS and then we manually need to save it. + + // "create()" will take number of arguments which are to be stored in model + Product.create({ + // key:value + // we have created same constants above. + title: title, + imageUrl: imageUrl, + price: price, + description: description + }) + // it will return a promise + .then(result => { + console.log(result); + console.log('product saved '); + + }) + .catch(err => { + console.log(err); + }); + }; exports.getEditProduct = (req, res, next) => { diff --git a/model/product.js b/model/product.js index b4f9780..ac1956f 100644 --- a/model/product.js +++ b/model/product.js @@ -1,39 +1,3 @@ -/************************************************************** - -const db = require('../util/database'); - -const Cart = require('./cart'); - -module.exports = class Product { - - constructor(id, title, imageUrl, description, price) { - this.id = id; - this.title = title; - this.imageUrl = imageUrl; - this.description = description; - this.price = price; - } - - save() { - return db.execute('INSERT INTO products(title, imageUrl, price, description) VALUES (?,?,?,?)', - [this.title, this.imageUrl, this.price, this.description]); - }; - - static deleteById(id) { - - }; - - static fetchAll() { - return db.execute('SELECT * FROM products'); - }; - - static findById(id) { - return db.execute('SELECT * FROM products WHERE products.id = ?', [id]); - } -}; - -*****************************************************************/ - const Sequelize = require('sequelize'); const sequelize = require('../util/database'); diff --git a/notes.txt b/notes.txt index 51eccf3..c624e87 100644 --- a/notes.txt +++ b/notes.txt @@ -5,7 +5,8 @@ model/products.js 11.149 app.js - +11.150 +controller/admin.js diff --git a/util/database.js b/util/database.js index f30ba93..142f774 100644 --- a/util/database.js +++ b/util/database.js @@ -1,39 +1,14 @@ -// const mysql = require('mysql2'); +// proper and nomal way +// const Sequelize = require('sequelize'); -// const pool = mysql.createPool({ -// host: 'localhost', -// user: 'root', -// database: 'nodeapp', -// password: 'root' -// }); +// this is buggy, using to get intellisense working +const Sequelize = require('sequelize').Sequelize; -// module.exports = pool.promise(); - - - - -// first step is to craete a model with sequlize and connect with database -// deleting other tables in database if there (because we want sequlize to manage our tables) -// connecting to database -// even though we are not importing mysql but it uses mysql behind the sceans - -const Sequelize = require('sequelize'); -// "Sequelize" is constructor function... its a class - -// creating the new instance of Sequelize -// Sequelize() accepts numbers of paramerters username, password,database, password -// 1: database name -// 2: username -// 3. password -// 4: option objects {} -// dialect: tells which database we are using . this is nessary as different sql databases have littel different sql syntax -// host: by default it will use localhost, but we set explicitly const sequelize = new Sequelize('nodeapp', 'root', 'root', { dialect: 'mysql', host: 'localhost' }); -// thus, this will create connection pool with sequelize object module.exports = sequelize; From 8603dc944bed6137bc6580424fbc189abdc556ce Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Sun, 19 Jan 2020 22:35:16 +0530 Subject: [PATCH 40/50] 152 Retrieving Data Finding Products --- controller/admin.js | 18 ------------------ controller/shop.js | 45 +++++++++++++++++++++++++++++++++++++-------- notes.txt | 4 ++-- 3 files changed, 39 insertions(+), 28 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index b3597f9..d6de848 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -14,30 +14,12 @@ exports.postAddProduct = (req, res, next) => { const description = req.body.description; const price = req.body.price; - // const product = new Product(null, title, imageUrl, description, price); - - // product.save() - // .then(() => { - // res.redirect("/"); - // }) - // .catch(err => console.log(err)); - - - // as we are using sequlize, we will add product by help of sequlize - - // "create()" creates a new element based on the model and immmeditely saves it to db. so, first we get object in JS first then it gets saved automatiavlly. - // "build()" also creates new object based on the model but only in JS and then we manually need to save it. - - // "create()" will take number of arguments which are to be stored in model Product.create({ - // key:value - // we have created same constants above. title: title, imageUrl: imageUrl, price: price, description: description }) - // it will return a promise .then(result => { console.log(result); console.log('product saved '); diff --git a/controller/shop.js b/controller/shop.js index 08071d7..cfc74ff 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -2,16 +2,26 @@ const Product = require('../model/product'); const Cart = require('../model/cart'); exports.getProduct = (req, res, next) => { - Product.fetchAll() - .then(([rows, fieldsData]) => { - console.log(rows); + Product.findAll() + .then(products => { res.render("shop/product-list", { pageTitle: "Shop Products", - prods: rows, + prods: products, path: "/products" }); }) .catch(err => console.log(err)); + + // Product.fetchAll() + // .then(([rows, fieldsData]) => { + // console.log(rows); + // res.render("shop/product-list", { + // pageTitle: "Shop Products", + // prods: rows, + // path: "/products" + // }); + // }) + // .catch(err => console.log(err)); }; exports.getDetails = (req, res, next) => { @@ -78,16 +88,35 @@ exports.getOrders = (req, res, next) => { }; exports.getIndex = (req, res, next) => { - Product.fetchAll() - .then(([rows]) => { + // "findAll()" is inbuild mathod in sequelise which gives all the data which is stored in model + // we can restrict elements which are retrived by giving conditions + // EG: + // Product.findAll({where: }) + // thus, findAll can accepts number of arugumets within it. + + Product.findAll() + .then(products => { res.render("shop/index", { pageTitle: "Shop", - prods: rows, + prods: products, path: "/" }); }) - .catch (err => console.log(err)); + .catch(err => console.log(err)); + + // as there is no "fetchAll()", this will not run + // Product.fetchAll() + // .then(([rows]) => { + // res.render("shop/index", { + // pageTitle: "Shop", + // prods: rows, + // path: "/" + // }); + // }) + // .catch (err => console.log(err)); }; + + diff --git a/notes.txt b/notes.txt index c624e87..0579548 100644 --- a/notes.txt +++ b/notes.txt @@ -8,8 +8,8 @@ app.js 11.150 controller/admin.js - - +11.152 +controller/shop.js From 665864431c8cd6b911aabecf0fd8c6a3c9864a46 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Sun, 19 Jan 2020 23:14:55 +0530 Subject: [PATCH 41/50] 153 Getting a Single Product with the where Condition --- controller/shop.js | 88 +++++++++++++++++++---------------- notes.txt | 11 +++++ public/css/main.css | 8 ++++ views/shop/product-detail.ejs | 2 +- 4 files changed, 68 insertions(+), 41 deletions(-) diff --git a/controller/shop.js b/controller/shop.js index cfc74ff..cfdfe11 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -11,37 +11,62 @@ exports.getProduct = (req, res, next) => { }); }) .catch(err => console.log(err)); - - // Product.fetchAll() - // .then(([rows, fieldsData]) => { - // console.log(rows); - // res.render("shop/product-list", { - // pageTitle: "Shop Products", - // prods: rows, - // path: "/products" - // }); - // }) - // .catch(err => console.log(err)); }; exports.getDetails = (req, res, next) => { const productID = req.params.productId; - // Product.findById(productID, product => { - // res.render('shop/product-detail', { pageTitle: product.title, product: product, path: '/products' }); - // }); - Product.findById(productID) - .then(([product]) => { - console.log(product); + // "findByPk" is also inbuild function. Pk:primary key + // It will gives us one single element object (not array) + + // Product.findByPk(productID) + // .then(product => { + // console.log(product); + // res.render( + // 'shop/product-detail', + // { pageTitle: product.title, + // product: product, + // path: '/products' + // } + // ); + // }) + // .catch(err => console.log(err)); + + // or + // using findAll() method + // it will give us result in array formate, so we have to specifu the array index ie "0" as there will be only one product with unique Pk. + Product.findAll({where : + {id: productID} + }) + .then(product => { + // console.log(product[0]); res.render( - 'shop/product-detail', - { pageTitle: product.title, - product: product[0], - path: '/products' - } - ); + 'shop/product-detail', + { + // specifying the index + pageTitle: product[0].title, + // specifying the index + product: product[0], + path: '/products' + } + ); }) .catch(err => console.log(err)); + + + // orlder way + // Product.findById(productID) + // .then(([product]) => { + // console.log(product); + // res.render( + // 'shop/product-detail', + // { pageTitle: product.title, + // product: product[0], + // path: '/products' + // } + // ); + // }) + // .catch(err => console.log(err)); }; exports.getCart = (req, res, next) => { @@ -88,12 +113,6 @@ exports.getOrders = (req, res, next) => { }; exports.getIndex = (req, res, next) => { - // "findAll()" is inbuild mathod in sequelise which gives all the data which is stored in model - // we can restrict elements which are retrived by giving conditions - // EG: - // Product.findAll({where: }) - // thus, findAll can accepts number of arugumets within it. - Product.findAll() .then(products => { res.render("shop/index", { @@ -103,17 +122,6 @@ exports.getIndex = (req, res, next) => { }); }) .catch(err => console.log(err)); - - // as there is no "fetchAll()", this will not run - // Product.fetchAll() - // .then(([rows]) => { - // res.render("shop/index", { - // pageTitle: "Shop", - // prods: rows, - // path: "/" - // }); - // }) - // .catch (err => console.log(err)); }; diff --git a/notes.txt b/notes.txt index 0579548..5cd623b 100644 --- a/notes.txt +++ b/notes.txt @@ -11,6 +11,17 @@ controller/admin.js 11.152 controller/shop.js +11.153 +product-detal.ejs : added class="image" +main.css : + .image { + height: 20rem; + } + + .image img { + height: 100%; + } +controller/shop.js diff --git a/public/css/main.css b/public/css/main.css index 5687205..2ffca14 100644 --- a/public/css/main.css +++ b/public/css/main.css @@ -197,6 +197,14 @@ form { text-align: center; } +.image { + height: 20rem; +} + +.image img { + height: 100%; +} + @media (min-width: 768px) { .main-header__nav { display: flex; diff --git a/views/shop/product-detail.ejs b/views/shop/product-detail.ejs index dbea8f0..4b346f6 100644 --- a/views/shop/product-detail.ejs +++ b/views/shop/product-detail.ejs @@ -7,7 +7,7 @@

    <%= product.title %>


    - <%= product.title %> + <%= product.title %>

    <%= product.price %>

    <%= product.description %>

    From 6aab013185188882bab0dedd5bc93875affac316 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Sun, 19 Jan 2020 23:55:41 +0530 Subject: [PATCH 42/50] 154 Fetching Admin Products --- controller/admin.js | 27 +++++++++++++-------------- controller/shop.js | 24 +----------------------- notes.txt | 14 ++------------ 3 files changed, 16 insertions(+), 49 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index d6de848..7c6113d 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -38,16 +38,6 @@ exports.getEditProduct = (req, res, next) => { } const productID = req.params.productID; - // Product.findById(productID, product => { - // res.render("admin/edit-product", { - // path: "/admin/edit-product", - // pageTitle: "Edit Products", - // editing: editMode, - // product: product - // }); - // }); - - // done in advance Product.findById(productID) .then(([row]) => { res.render("admin/edit-product", { @@ -75,19 +65,28 @@ exports.postEditProduct = (req, res, next) => { exports.postDeleteProduct = (req, res, next) => { const productID = req.body.productID; - // Product.deleteById(productID); - - // it will be better if we have callback to this, so that it should redirect, once it is done. Product.deleteById(productID); res.redirect('/admin/products'); }; exports.getProducts = (req, res, next) => { - Product.fetchAll((products) => { + Product.findAll() + .then(products => { res.render("admin/products", { path: "/admin/products", pageTitle: "Admin Add Products", prods: products, }); }) + .catch(err => { + console.log(err); + }); + + // Product.fetchAll((products) => { + // res.render("admin/products", { + // path: "/admin/products", + // pageTitle: "Admin Add Products", + // prods: products, + // }); + // }) }; \ No newline at end of file diff --git a/controller/shop.js b/controller/shop.js index cfdfe11..ba17f1a 100644 --- a/controller/shop.js +++ b/controller/shop.js @@ -16,9 +16,6 @@ exports.getProduct = (req, res, next) => { exports.getDetails = (req, res, next) => { const productID = req.params.productId; - // "findByPk" is also inbuild function. Pk:primary key - // It will gives us one single element object (not array) - // Product.findByPk(productID) // .then(product => { // console.log(product); @@ -33,40 +30,21 @@ exports.getDetails = (req, res, next) => { // .catch(err => console.log(err)); // or - // using findAll() method - // it will give us result in array formate, so we have to specifu the array index ie "0" as there will be only one product with unique Pk. + Product.findAll({where : {id: productID} }) .then(product => { - // console.log(product[0]); res.render( 'shop/product-detail', { - // specifying the index pageTitle: product[0].title, - // specifying the index product: product[0], path: '/products' } ); }) .catch(err => console.log(err)); - - - // orlder way - // Product.findById(productID) - // .then(([product]) => { - // console.log(product); - // res.render( - // 'shop/product-detail', - // { pageTitle: product.title, - // product: product[0], - // path: '/products' - // } - // ); - // }) - // .catch(err => console.log(err)); }; exports.getCart = (req, res, next) => { diff --git a/notes.txt b/notes.txt index 5cd623b..a8285e2 100644 --- a/notes.txt +++ b/notes.txt @@ -1,16 +1,4 @@ -11.148 -model/products.js - -11.149 -app.js - -11.150 -controller/admin.js - -11.152 -controller/shop.js - 11.153 product-detal.ejs : added class="image" main.css : @@ -23,6 +11,8 @@ main.css : } controller/shop.js +11.154 +controller/admin.js : getProducts From d6c9043627afd836e7344d9b59969cd74f156bcc Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Mon, 20 Jan 2020 00:13:23 +0530 Subject: [PATCH 43/50] 155 Updating Products --- controller/admin.js | 67 ++++++++++++++++++++++++++++++--------------- notes.txt | 2 ++ 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index 7c6113d..b90a9da 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -36,18 +36,30 @@ exports.getEditProduct = (req, res, next) => { if(!editMode) { res.redirect('/'); } - const productID = req.params.productID; - Product.findById(productID) - .then(([row]) => { - res.render("admin/edit-product", { - path: "/admin/edit-product", - pageTitle: "Edit Products", - editing: editMode, - product: row - }); - }) - .catch(err => console.log(err)); + + Product.findByPk(productID) + .then(product => { + res.render("admin/edit-product", { + path: "/admin/edit-product", + pageTitle: "Edit Products", + editing: editMode, + product: product + }); + }) + .catch(err => console.log(err)); + + // older with SQL + // Product.findById(productID) + // .then(([row]) => { + // res.render("admin/edit-product", { + // path: "/admin/edit-product", + // pageTitle: "Edit Products", + // editing: editMode, + // product: row + // }); + // }) + // .catch(err => console.log(err)); }; @@ -58,9 +70,28 @@ exports.postEditProduct = (req, res, next) => { const updatedPrice = req.body.price; const upadatedDesciption = req.body.description; - const updatedProduct = new Product(productID, updatedTitle, updatedImageUrl, upadatedDesciption, updatedPrice); - updatedProduct.save(); - res.redirect('/admin/products'); + Product.findByPk(productID) + .then(product => { + // updating oder values with new values + product.title = updatedTitle; + product.imageUrl = updatedImageUrl; + product.price = updatedPrice; + product.description = upadatedDesciption; + + // "save()" is inbuild method provided by sequelize which will update values in database by taking updated values from JS + // if the product does not exist, it will creat a new product else if it is there, it will update existing one. + product.save() + }) + // this ".then()" is for save() mthod + .then(() => { + res.redirect('/admin/products'); + }) + .catch(err => console.log(err)); + + // older + // const updatedProduct = new Product(productID, updatedTitle, updatedImageUrl, upadatedDesciption, updatedPrice); + // updatedProduct.save(); + // res.redirect('/admin/products'); }; exports.postDeleteProduct = (req, res, next) => { @@ -81,12 +112,4 @@ exports.getProducts = (req, res, next) => { .catch(err => { console.log(err); }); - - // Product.fetchAll((products) => { - // res.render("admin/products", { - // path: "/admin/products", - // pageTitle: "Admin Add Products", - // prods: products, - // }); - // }) }; \ No newline at end of file diff --git a/notes.txt b/notes.txt index a8285e2..e3e45cb 100644 --- a/notes.txt +++ b/notes.txt @@ -14,6 +14,8 @@ controller/shop.js 11.154 controller/admin.js : getProducts +11.155 +controller/admin.js From 1a432684dc6533de25c826270dc77bf1f626fc86 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Mon, 20 Jan 2020 00:44:18 +0530 Subject: [PATCH 44/50] 156 Deleting Products --- controller/admin.js | 51 ++++++++++++++++++++++----------------------- notes.txt | 2 ++ 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/controller/admin.js b/controller/admin.js index b90a9da..cd92397 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -21,9 +21,9 @@ exports.postAddProduct = (req, res, next) => { description: description }) .then(result => { - console.log(result); + // console.log(result); console.log('product saved '); - + res.redirect('/admin/products'); }) .catch(err => { console.log(err); @@ -48,19 +48,6 @@ exports.getEditProduct = (req, res, next) => { }); }) .catch(err => console.log(err)); - - // older with SQL - // Product.findById(productID) - // .then(([row]) => { - // res.render("admin/edit-product", { - // path: "/admin/edit-product", - // pageTitle: "Edit Products", - // editing: editMode, - // product: row - // }); - // }) - // .catch(err => console.log(err)); - }; exports.postEditProduct = (req, res, next) => { @@ -72,32 +59,44 @@ exports.postEditProduct = (req, res, next) => { Product.findByPk(productID) .then(product => { - // updating oder values with new values product.title = updatedTitle; product.imageUrl = updatedImageUrl; product.price = updatedPrice; product.description = upadatedDesciption; - // "save()" is inbuild method provided by sequelize which will update values in database by taking updated values from JS - // if the product does not exist, it will creat a new product else if it is there, it will update existing one. product.save() }) - // this ".then()" is for save() mthod .then(() => { res.redirect('/admin/products'); }) .catch(err => console.log(err)); - - // older - // const updatedProduct = new Product(productID, updatedTitle, updatedImageUrl, upadatedDesciption, updatedPrice); - // updatedProduct.save(); - // res.redirect('/admin/products'); }; exports.postDeleteProduct = (req, res, next) => { const productID = req.body.productID; - Product.deleteById(productID); - res.redirect('/admin/products'); + + // 1st method : we passing product model. so we have pass the query to tell which product to delete + // Product.destroy(where : {product.id = productID}); + // Product.destroy(); //error, as no condition will pass + + // 2nd method + Product.findByPk(productID) + .then(product => { + // here we are passing product object, thus it will get deleted + product.destroy() + + // or + // return product.destroy() + }) + .then(() => { + res.redirect('/admin/products'); + }) + .catch(err => console.log(err)); + + + // older + // Product.deleteById(productID); + // res.redirect('/admin/products'); }; exports.getProducts = (req, res, next) => { diff --git a/notes.txt b/notes.txt index e3e45cb..564cbd6 100644 --- a/notes.txt +++ b/notes.txt @@ -17,6 +17,8 @@ controller/admin.js : getProducts 11.155 controller/admin.js +11.156 +controller/admin.js : delete From b6232a2b2523d484557bbed6597830bf92d972a7 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Mon, 20 Jan 2020 01:07:58 +0530 Subject: [PATCH 45/50] 157 Creating a User Model --- controller/admin.js | 11 +---------- model/user.js | 22 ++++++++++++++++++++++ notes.txt | 22 ++-------------------- 3 files changed, 25 insertions(+), 30 deletions(-) create mode 100644 model/user.js diff --git a/controller/admin.js b/controller/admin.js index cd92397..926f425 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -76,27 +76,18 @@ exports.postDeleteProduct = (req, res, next) => { const productID = req.body.productID; // 1st method : we passing product model. so we have pass the query to tell which product to delete - // Product.destroy(where : {product.id = productID}); + // Product.destroy({}); // Product.destroy(); //error, as no condition will pass // 2nd method Product.findByPk(productID) .then(product => { - // here we are passing product object, thus it will get deleted product.destroy() - - // or - // return product.destroy() }) .then(() => { res.redirect('/admin/products'); }) .catch(err => console.log(err)); - - - // older - // Product.deleteById(productID); - // res.redirect('/admin/products'); }; exports.getProducts = (req, res, next) => { diff --git a/model/user.js b/model/user.js new file mode 100644 index 0000000..fbec618 --- /dev/null +++ b/model/user.js @@ -0,0 +1,22 @@ +const Sequelize = require('sequelize'); + +const sequelize = require('../util/database'); + +const User = sequelize.define(user, { + id : { + primaryKey: true, + allowNull: false, + autoIncrement: true, + type: Sequelize.INTEGER + }, + name : { + type: Sequelize.STRING, + allowNull: false + }, + email : { + type: Sequelize.STRING, + allowNull: false + } +}); + +module.exports = User; \ No newline at end of file diff --git a/notes.txt b/notes.txt index 564cbd6..ae659ab 100644 --- a/notes.txt +++ b/notes.txt @@ -1,26 +1,8 @@ - -11.153 -product-detal.ejs : added class="image" -main.css : - .image { - height: 20rem; - } - - .image img { - height: 100%; - } -controller/shop.js - -11.154 -controller/admin.js : getProducts - -11.155 -controller/admin.js - 11.156 controller/admin.js : delete - +11.157 +model/user.js From d11f3feab64c50e99a857e778b17de4934e4b4f9 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Mon, 20 Jan 2020 01:12:27 +0530 Subject: [PATCH 46/50] 157 Creating a User Model --- model/user.js | 2 ++ notes.txt | 1 + 2 files changed, 3 insertions(+) diff --git a/model/user.js b/model/user.js index fbec618..5e2d0f1 100644 --- a/model/user.js +++ b/model/user.js @@ -1,3 +1,5 @@ +// There will be one dummy user who can add items in cart and later can checkout. + const Sequelize = require('sequelize'); const sequelize = require('../util/database'); diff --git a/notes.txt b/notes.txt index ae659ab..cedaf16 100644 --- a/notes.txt +++ b/notes.txt @@ -2,6 +2,7 @@ controller/admin.js : delete 11.157 + There will be one dummy user who can add items in cart and later can checkout. model/user.js From 31caebf55dded087159dc7b483a37d5c40c2a44e Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Mon, 20 Jan 2020 01:40:27 +0530 Subject: [PATCH 47/50] 158 Adding a One-To-Many Relationship --- app.js | 18 +++++++++++++++++- model/user.js | 3 ++- notes.txt | 2 ++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 87646b3..a15965f 100644 --- a/app.js +++ b/app.js @@ -9,6 +9,10 @@ const rootDir = require('./util/path'); const errorController = require('./controller/error'); const sequelize = require('./util/database'); +// requrering both the models +const Product = require('./model/product'); +const User = require('./model/user'); + const app = express(); app.set('view engine', 'ejs'); @@ -22,7 +26,19 @@ app.use(shopRoutes); app.use(errorController.get404); -sequelize.sync() +// assocaiation between tables +// "belongsTo" tells that user can have many products +// "{constraints: true, onDelete: 'CASCADE'}" these are optioanl to write, not nessary. +// "CASCADE" if user is deleted, product associating will also get deleted +Product.belongsTo(User, {constraints: true, onDelete: 'CASCADE'}); +// "hasMany" also means the same, thus optinal to write. +User.hasMany(Product); + +// we alraedy created our tables in db, earlier. so these new assoications cant be assigned. +// to make changes to existing tables, we will pass an arguments to sync() method. ie "{force: true}" +// this should be used only at development tym, as we dont want to write our new table over existing table. + +sequelize.sync({force: true}) .then(result => { // console.log('result' ,result); app.listen(3000); diff --git a/model/user.js b/model/user.js index 5e2d0f1..387ad53 100644 --- a/model/user.js +++ b/model/user.js @@ -4,7 +4,8 @@ const Sequelize = require('sequelize'); const sequelize = require('../util/database'); -const User = sequelize.define(user, { +// table name will be in single quotes '' +const User = sequelize.define('user', { id : { primaryKey: true, allowNull: false, diff --git a/notes.txt b/notes.txt index cedaf16..3160ddf 100644 --- a/notes.txt +++ b/notes.txt @@ -5,6 +5,8 @@ controller/admin.js : delete There will be one dummy user who can add items in cart and later can checkout. model/user.js +11.158 +app.js From a4ae894d11a76870b6464e4b7d6c110824938f2c Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Mon, 20 Jan 2020 02:32:13 +0530 Subject: [PATCH 48/50] 159 Creating Managing a Dummy User --- app.js | 65 ++++++++++++++++++++++++++++++++++++--------- controller/admin.js | 6 ----- notes.txt | 11 ++------ 3 files changed, 54 insertions(+), 28 deletions(-) diff --git a/app.js b/app.js index a15965f..f24e2ee 100644 --- a/app.js +++ b/app.js @@ -9,7 +9,7 @@ const rootDir = require('./util/path'); const errorController = require('./controller/error'); const sequelize = require('./util/database'); -// requrering both the models +// requiring both the models const Product = require('./model/product'); const User = require('./model/user'); @@ -21,27 +21,66 @@ app.set('views', 'views'); app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static(path.join(rootDir, 'public'))); +// registering the new middleware, because we want to store that user in our request so that we can use it from anywhere in our app +app.use((req, res, next) => { + // now we want to reachout to our database and retrive the user + // with the help of + // User.findByPk(1); + + // IMPORTANT: + // you might think that will this ever return a user if are craeting down in sync() method + // app only registered the middleware function. so for incoming request, it will then execute this middleware function + // npm start will first run sequelize.sync() and then user ill get registed if it not there, then server runs + // once the server start running, request will be made and this function will get executed + + User.findByPk(1) + .then((user) => { + // we want to storethe user in request + req.user = user; + // we can do that, we are just adding the user field to "req" object + // we just have to amke sure, we dont overwrite the exisiting user + // "req.user = user;" here user is undefined by default, so now we are storing user which we retrived from the database + // user which are reterving is not just a JS object with values stored in db and .Its a sequelize object with values stored in the database and with all the utility methods sequelize added like destroy. + // thus, we are storing sequelize object in request object, not just JS object + // hence whenver we user now, we can operate sequelize methods on it. + + // we need to call "next()" so taht we can continue with the next step if we get our user and store it. + next(); + }) + .catch(err => console.log(err)); +}); + app.use('/admin', adminRoutes); app.use(shopRoutes); app.use(errorController.get404); -// assocaiation between tables -// "belongsTo" tells that user can have many products -// "{constraints: true, onDelete: 'CASCADE'}" these are optioanl to write, not nessary. -// "CASCADE" if user is deleted, product associating will also get deleted Product.belongsTo(User, {constraints: true, onDelete: 'CASCADE'}); -// "hasMany" also means the same, thus optinal to write. User.hasMany(Product); - -// we alraedy created our tables in db, earlier. so these new assoications cant be assigned. -// to make changes to existing tables, we will pass an arguments to sync() method. ie "{force: true}" -// this should be used only at development tym, as we dont want to write our new table over existing table. -sequelize.sync({force: true}) +// sequelize.sync({force: true}) +sequelize.sync() .then(result => { - // console.log('result' ,result); - app.listen(3000); + // craeting a dummy user, which is logged in as sooon as server starts. + return User.findByPk(1) +}) +.then( user => { + if(!user) { + // here are passing promise + return User.create({name: 'max', email: 'test@t.com'}); + } + // but here only object will be returned. + // return user; + // we should always return the same so that next "then()" can be executed + // so, returning user promise + // return Promise.resolve(user); + // but no need of that as whatever is returned from "then()" is wrapped inside promise itself. hence + return user; +}) +.then(user => { + console.log(user); + // hence, user is registered successfully. and we can start the server + app.listen(3000); }) .catch(err => { console.log('err', err); diff --git a/controller/admin.js b/controller/admin.js index 926f425..7cf0500 100644 --- a/controller/admin.js +++ b/controller/admin.js @@ -74,12 +74,6 @@ exports.postEditProduct = (req, res, next) => { exports.postDeleteProduct = (req, res, next) => { const productID = req.body.productID; - - // 1st method : we passing product model. so we have pass the query to tell which product to delete - // Product.destroy({}); - // Product.destroy(); //error, as no condition will pass - - // 2nd method Product.findByPk(productID) .then(product => { product.destroy() diff --git a/notes.txt b/notes.txt index 3160ddf..61ea519 100644 --- a/notes.txt +++ b/notes.txt @@ -1,15 +1,8 @@ -11.156 -controller/admin.js : delete - -11.157 - There will be one dummy user who can add items in cart and later can checkout. -model/user.js - 11.158 app.js - - +11.159 +app.js From 5fb2fa5127f4978ca8e42730cc903f540c138669 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Mon, 20 Jan 2020 13:30:43 +0530 Subject: [PATCH 49/50] 159 Creating Managing a Dummy User --- app.js | 30 ------------------------------ notes.txt | 1 + 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/app.js b/app.js index f24e2ee..25e3ab6 100644 --- a/app.js +++ b/app.js @@ -21,30 +21,10 @@ app.set('views', 'views'); app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static(path.join(rootDir, 'public'))); -// registering the new middleware, because we want to store that user in our request so that we can use it from anywhere in our app app.use((req, res, next) => { - // now we want to reachout to our database and retrive the user - // with the help of - // User.findByPk(1); - - // IMPORTANT: - // you might think that will this ever return a user if are craeting down in sync() method - // app only registered the middleware function. so for incoming request, it will then execute this middleware function - // npm start will first run sequelize.sync() and then user ill get registed if it not there, then server runs - // once the server start running, request will be made and this function will get executed - User.findByPk(1) .then((user) => { - // we want to storethe user in request req.user = user; - // we can do that, we are just adding the user field to "req" object - // we just have to amke sure, we dont overwrite the exisiting user - // "req.user = user;" here user is undefined by default, so now we are storing user which we retrived from the database - // user which are reterving is not just a JS object with values stored in db and .Its a sequelize object with values stored in the database and with all the utility methods sequelize added like destroy. - // thus, we are storing sequelize object in request object, not just JS object - // hence whenver we user now, we can operate sequelize methods on it. - - // we need to call "next()" so taht we can continue with the next step if we get our user and store it. next(); }) .catch(err => console.log(err)); @@ -58,28 +38,18 @@ app.use(errorController.get404); Product.belongsTo(User, {constraints: true, onDelete: 'CASCADE'}); User.hasMany(Product); -// sequelize.sync({force: true}) sequelize.sync() .then(result => { - // craeting a dummy user, which is logged in as sooon as server starts. return User.findByPk(1) }) .then( user => { if(!user) { - // here are passing promise return User.create({name: 'max', email: 'test@t.com'}); } - // but here only object will be returned. - // return user; - // we should always return the same so that next "then()" can be executed - // so, returning user promise - // return Promise.resolve(user); - // but no need of that as whatever is returned from "then()" is wrapped inside promise itself. hence return user; }) .then(user => { console.log(user); - // hence, user is registered successfully. and we can start the server app.listen(3000); }) .catch(err => { diff --git a/notes.txt b/notes.txt index 61ea519..f1003a0 100644 --- a/notes.txt +++ b/notes.txt @@ -10,3 +10,4 @@ app.js + From 128fa8b5c458acb26389fde14010e68ea42ceaf9 Mon Sep 17 00:00:00 2001 From: Bhagat Singh Date: Mon, 20 Jan 2020 19:39:52 +0530 Subject: [PATCH 50/50] 159 Creating Managing a Dummy User --- app.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/app.js b/app.js index 25e3ab6..f24e2ee 100644 --- a/app.js +++ b/app.js @@ -21,10 +21,30 @@ app.set('views', 'views'); app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static(path.join(rootDir, 'public'))); +// registering the new middleware, because we want to store that user in our request so that we can use it from anywhere in our app app.use((req, res, next) => { + // now we want to reachout to our database and retrive the user + // with the help of + // User.findByPk(1); + + // IMPORTANT: + // you might think that will this ever return a user if are craeting down in sync() method + // app only registered the middleware function. so for incoming request, it will then execute this middleware function + // npm start will first run sequelize.sync() and then user ill get registed if it not there, then server runs + // once the server start running, request will be made and this function will get executed + User.findByPk(1) .then((user) => { + // we want to storethe user in request req.user = user; + // we can do that, we are just adding the user field to "req" object + // we just have to amke sure, we dont overwrite the exisiting user + // "req.user = user;" here user is undefined by default, so now we are storing user which we retrived from the database + // user which are reterving is not just a JS object with values stored in db and .Its a sequelize object with values stored in the database and with all the utility methods sequelize added like destroy. + // thus, we are storing sequelize object in request object, not just JS object + // hence whenver we user now, we can operate sequelize methods on it. + + // we need to call "next()" so taht we can continue with the next step if we get our user and store it. next(); }) .catch(err => console.log(err)); @@ -38,18 +58,28 @@ app.use(errorController.get404); Product.belongsTo(User, {constraints: true, onDelete: 'CASCADE'}); User.hasMany(Product); +// sequelize.sync({force: true}) sequelize.sync() .then(result => { + // craeting a dummy user, which is logged in as sooon as server starts. return User.findByPk(1) }) .then( user => { if(!user) { + // here are passing promise return User.create({name: 'max', email: 'test@t.com'}); } + // but here only object will be returned. + // return user; + // we should always return the same so that next "then()" can be executed + // so, returning user promise + // return Promise.resolve(user); + // but no need of that as whatever is returned from "then()" is wrapped inside promise itself. hence return user; }) .then(user => { console.log(user); + // hence, user is registered successfully. and we can start the server app.listen(3000); }) .catch(err => {