Skip to content

Commit 422637d

Browse files
committed
first commit
0 parents  commit 422637d

30 files changed

+2166
-0
lines changed

app.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const path = require('path');
2+
3+
const express = require('express');
4+
const bodyParser = require('body-parser');
5+
6+
const errorController = require('./controllers/error');
7+
8+
const app = express();
9+
10+
app.set('view engine', 'ejs');
11+
app.set('views', 'views');
12+
13+
const adminRoutes = require('./routes/admin');
14+
const shopRoutes = require('./routes/shop');
15+
16+
app.use(bodyParser.urlencoded({ extended: false }));
17+
app.use(express.static(path.join(__dirname, 'public')));
18+
19+
app.use('/admin', adminRoutes);
20+
app.use(shopRoutes);
21+
22+
app.use(errorController.get404);
23+
24+
app.listen(3000);
25+
26+
// https://www.publicdomainpictures.net/pictures/10000/velka/1-1210009435EGmE.jpg

controllers/admin.js

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
const Product = require('../models/product');
2+
3+
exports.getAddProduct = (req, res, next) => {
4+
res.render('admin/edit-product', {
5+
pageTitle: 'Add Product',
6+
path: '/admin/add-product',
7+
editing: false
8+
});
9+
};
10+
11+
exports.postAddProduct = (req, res, next) => {
12+
const title = req.body.title;
13+
const imageUrl = req.body.imageUrl;
14+
const price = req.body.price;
15+
const description = req.body.description;
16+
const product = new Product(null, title, imageUrl, description, price);
17+
product.save();
18+
res.redirect('/');
19+
};
20+
21+
exports.getEditProduct = (req, res, next) => {
22+
const editMode = req.query.edit;
23+
if (!editMode) {
24+
return res.redirect('/');
25+
}
26+
27+
const prodId = req.params.productId;
28+
Product.findById(prodId, product => {
29+
if (!product) {
30+
return res.redirect('/')
31+
}
32+
res.render('admin/edit-product', {
33+
pageTitle: 'Edit Product',
34+
path: '/admin/edit-product',
35+
editing: editMode,
36+
product: product
37+
});
38+
});
39+
};
40+
41+
exports.postEditProduct = (req, res, next) => {
42+
const prodId = req.body.productId;
43+
const updatedTitle = req.body.title;
44+
const updatedPrice = req.body.price;
45+
const updatedImageUrl = req.body.imageUrl;
46+
const updatedDesc = req.body.description;
47+
const updatedProduct = new Product(
48+
prodId,
49+
updatedTitle,
50+
updatedImageUrl,
51+
updatedDesc,
52+
updatedPrice
53+
);
54+
updatedProduct.save();
55+
res.redirect('/admin/products');
56+
};
57+
58+
exports.getProducts = (req, res, next) => {
59+
Product.fetchAll(products => {
60+
res.render('admin/products', {
61+
prods: products,
62+
pageTitle: 'Admin Products',
63+
path: '/admin/products'
64+
});
65+
});
66+
};
67+
68+
exports.postDeleteProduct = (req, res, next) => {
69+
const prodId = req.body.productId;
70+
Product.deleteById(prodId);
71+
res.redirect('/admin/products');
72+
};

controllers/error.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
exports.get404 = (req, res, next) => {
2+
res.status(404).render('404', { pageTitle: 'Page Not Found', path: '/404' });
3+
};

controllers/shop.js

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
const Product = require('../models/product');
2+
const Cart = require('../models/cart');
3+
4+
exports.getProducts = (req, res, next) => {
5+
Product.fetchAll(products => {
6+
res.render('shop/product-list', {
7+
prods: products,
8+
pageTitle: 'All Products',
9+
path: '/products'
10+
});
11+
});
12+
};
13+
14+
exports.getProduct = (req, res, next) => {
15+
const prodId = req.params.productId;
16+
Product.findById(prodId, product => {
17+
res.render('shop/product-detail', {
18+
product: product,
19+
pageTitle: product.title,
20+
path: '/products'
21+
});
22+
});
23+
};
24+
25+
exports.getIndex = (req, res, next) => {
26+
Product.fetchAll(products => {
27+
res.render('shop/index', {
28+
prods: products,
29+
pageTitle: 'Shop',
30+
path: '/'
31+
});
32+
});
33+
};
34+
35+
exports.getCart = (req, res, next) => {
36+
Cart.getCart(cart => {
37+
Product.fetchAll(products => {
38+
const cartProducts = [];
39+
for (product of products) {
40+
const cartProductData = cart.products.find(prod => prod.id === product.id);
41+
if (cartProductData) {
42+
cartProducts.push({ productData: product, qty: cartProductData.qty });
43+
}
44+
}
45+
res.render('shop/cart', {
46+
path: '/cart',
47+
pageTitle: 'Your Cart',
48+
products: cartProducts
49+
});
50+
});
51+
});
52+
};
53+
54+
exports.postCart = (req, res, next) => {
55+
const prodId = req.body.productId;
56+
Product.findById(prodId, product => {
57+
Cart.addProduct(prodId, product.price);
58+
});
59+
res.redirect('/cart');
60+
};
61+
62+
exports.postCartDeleteProduct = (req, res, next) => {
63+
const prodId = req.body.productId;
64+
Product.findById(prodId, product => {
65+
Cart.deleteProduct(prodId, product.price);
66+
res.redirect('/cart');
67+
});
68+
}
69+
70+
exports.getOrders = (req, res, next) => {
71+
res.render('shop/orders', {
72+
path: '/orders',
73+
pageTitle: 'Your Orders'
74+
});
75+
};
76+
77+
exports.getCheckout = (req, res, next) => {
78+
res.render('shop/checkout', {
79+
path: '/checkout',
80+
pageTitle: 'Checkout'
81+
});
82+
};

data/cart.json

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"products":[],"totalPrice":0}

data/products.json

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"id":"0.8380178655222026","title":"Alchemist","imageUrl":"https://www.publicdomainpictures.net/pictures/10000/velka/1-1210009435EGmE.jpg","description":"An Adventure Journey Book By Paulo Cohelo","price":"20.55"}]

models/cart.js

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
4+
const p = path.join(
5+
path.dirname(process.mainModule.filename),
6+
'data',
7+
'cart.json'
8+
);
9+
10+
module.exports = class Cart {
11+
static addProduct(id, productPrice) {
12+
// Fetch the previous cart
13+
fs.readFile(p, (err, fileContent) => {
14+
let cart = { products: [], totalPrice: 0 };
15+
if (!err) {
16+
cart = JSON.parse(fileContent);
17+
}
18+
// Analyze the cart => Find existing product
19+
const existingProductIndex = cart.products.findIndex(
20+
prod => prod.id === id
21+
);
22+
const existingProduct = cart.products[existingProductIndex];
23+
let updatedProduct;
24+
// Add new product/ increase quantity
25+
if (existingProduct) {
26+
updatedProduct = { ...existingProduct };
27+
updatedProduct.qty = updatedProduct.qty + 1;
28+
cart.products = [...cart.products];
29+
cart.products[existingProductIndex] = updatedProduct;
30+
} else {
31+
updatedProduct = { id: id, qty: 1 };
32+
cart.products = [...cart.products, updatedProduct];
33+
}
34+
cart.totalPrice = cart.totalPrice + +productPrice;
35+
fs.writeFile(p, JSON.stringify(cart), err => {
36+
console.log(err);
37+
});
38+
});
39+
}
40+
41+
static deleteProduct(id, productPrice) {
42+
fs.readFile(p, (err, fileContent) => {
43+
if (err) {
44+
return;
45+
}
46+
const updatedCart = { ...JSON.parse(fileContent) };
47+
const product = updatedCart.products.find(prod => prod.id === id);
48+
if (!product) {
49+
return;
50+
}
51+
const productQty = product.qty;
52+
updatedCart.products = updatedCart.products.filter( prod => prod.id !== id );
53+
updatedCart.totalPrice = updatedCart.totalPrice - productPrice * productQty;
54+
fs.writeFile(p, JSON.stringify(updatedCart), err => {
55+
console.log(err);
56+
});
57+
});
58+
}
59+
60+
static getCart(cb) {
61+
fs.readFile(p, (err, fileContent) => {
62+
const cart = JSON.parse(fileContent);
63+
if (err) {
64+
cb(null);
65+
} else {
66+
cb(cart);
67+
}
68+
});
69+
}
70+
};

models/product.js

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
4+
const Cart = require('./cart');
5+
6+
const p = path.join(
7+
path.dirname(process.mainModule.filename),
8+
'data',
9+
'products.json'
10+
);
11+
12+
const getProductsFromFile = cb => {
13+
fs.readFile(p, (err, fileContent) => {
14+
if (err) {
15+
cb([]);
16+
} else {
17+
cb(JSON.parse(fileContent));
18+
}
19+
});
20+
};
21+
22+
module.exports = class Product {
23+
constructor(id, title, imageUrl, description, price) {
24+
this.id = id;
25+
this.title = title;
26+
this.imageUrl = imageUrl;
27+
this.description = description;
28+
this.price = price;
29+
}
30+
31+
save() {
32+
getProductsFromFile(products => {
33+
if (this.id) {
34+
const existingProductIndex = products.findIndex(
35+
prod => prod.id === this.id
36+
);
37+
const updatedProducts = [...products];
38+
updatedProducts[existingProductIndex] = this;
39+
fs.writeFile(p, JSON.stringify(updatedProducts), err => {
40+
console.log(err);
41+
});
42+
} else {
43+
this.id = Math.random().toString();
44+
products.push(this);
45+
fs.writeFile(p, JSON.stringify(products), err => {
46+
console.log(err);
47+
});
48+
}
49+
});
50+
}
51+
52+
static deleteById(id) {
53+
getProductsFromFile(products => {
54+
const product = products.find(prod => prod.id === id);
55+
const updatedProducts = products.filter(prod => prod.id !== id);
56+
fs.writeFile(p, JSON.stringify(updatedProducts), err => {
57+
if (!err) {
58+
Cart.deleteProduct(id, product.price);
59+
}
60+
});
61+
});
62+
}
63+
64+
static fetchAll(cb) {
65+
getProductsFromFile(cb);
66+
}
67+
68+
static findById(id, cb) {
69+
getProductsFromFile(products => {
70+
const product = products.find(p => p.id === id);
71+
cb(product);
72+
});
73+
}
74+
};

0 commit comments

Comments
 (0)