Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a0e62fd
setting up and installing packages
svbarker Aug 9, 2017
1147594
models and migrations
gregfilipczak Aug 9, 2017
bee86cd
setting up seeders
svbarker Aug 9, 2017
cc13179
working on seeds
gregfilipczak Aug 9, 2017
1587f03
seeding works, working on rendering all products with their category …
svbarker Aug 9, 2017
30afd65
setting up the search in the view
svbarker Aug 9, 2017
c76a937
tweaked the styling
svbarker Aug 9, 2017
c5c2ed1
added images to Product model
svbarker Aug 9, 2017
9ed626c
mongoose seeds
gregfilipczak Aug 9, 2017
7f85528
working on Mongoose setup
svbarker Aug 9, 2017
8f1e9ce
mongoose works! don't touch anything
svbarker Aug 9, 2017
6b865ea
product view
gregfilipczak Aug 9, 2017
e457761
working on filters
svbarker Aug 9, 2017
dafcda2
working filter
gregfilipczak Aug 9, 2017
a8ec171
made sure related products don't show current product
svbarker Aug 9, 2017
5e3acc6
search functionality working
svbarker Aug 10, 2017
3c96a32
integrated all searching and filtering together
svbarker Aug 10, 2017
7e9926b
made a cart view
svbarker Aug 10, 2017
eda0559
working on saving and displaying carts
svbarker Aug 10, 2017
35368b8
carts are saved in sessions and contents display properly
svbarker Aug 10, 2017
bcfe186
cart page displays message when no items in cart
svbarker Aug 10, 2017
00c1ea3
can now set quantities on the cart page
svbarker Aug 10, 2017
ae81d2c
can remove single item from cart
svbarker Aug 10, 2017
735fb21
setting quantity to 0 now removes item
svbarker Aug 10, 2017
b3178f2
quantities will only accept positive numeric values
svbarker Aug 10, 2017
6bc036b
add/edit cart buttons update based on user cart; needs refactoring
svbarker Aug 10, 2017
13bb828
checkout displaying properly
svbarker Aug 10, 2017
cde8d8e
starting on Stripe checkouts
svbarker Aug 10, 2017
66a299f
successfully check out and save orders to the database
svbarker Aug 11, 2017
cef88ff
order seeders and order display work
svbarker Aug 11, 2017
edfb0da
added navigation
svbarker Aug 11, 2017
e1b9243
analytics work, and finally got around to creating a states table
svbarker Aug 11, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
.env
17 changes: 17 additions & 0 deletions .sequelizerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
var path = require("path");

// Set options
var config = {
config: "./config/sequelize.js",
"migrations-path": "./migrations/sequelize",
"seeders-path": "./seeds/sequelize",
"models-path": "./models/sequelize"
};

// Resolve paths to absolute paths
Object.keys(config).forEach(key => {
config[key] = path.resolve(config[key]);
});

// Export like any normal module
module.exports = config;
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
Greg and Stephanie

# project_mimirs_market
A Viking eCommerce store for Thunder Gods that like to buy "Antique Wooden Pizzas"
59 changes: 59 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const express = require("express");
const app = express();
const exphbs = require("express-handlebars");
const bodyParser = require("body-parser");
const methodOverride = require("method-override");
const getPostSupport = require("express-method-override-get-post-support");
const session = require("express-session");
const mongooseModels = require("./models/mongoose");
const sqlModels = require("./models/sequelize");
const ProductsController = require("./controllers/products");
const mongoose = require("mongoose");

const products = require("./routes/products");
const cart = require("./routes/cart");
const checkout = require("./routes/checkout");
const admin = require("./routes/admin");

if (process.env.NODE_ENV !== "production") {
require("dotenv").config();
}

app.use(bodyParser.urlencoded({ extended: true }));
app.use(methodOverride(getPostSupport.callback, getPostSupport.options));

app.use(express.static(__dirname + "/public"));

const hbs = exphbs.create({
partialsDir: "views/partials",
defaultLayout: "main"
});
app.engine("handlebars", hbs.engine);
app.set("view engine", "handlebars");

app.use(
session({
secret: "123456",
resave: false,
saveUninitialized: true
})
);

app.use((req, res, next) => {
if (mongoose.connection.readyState) {
next();
} else {
require("./mongo")().then(() => next());
}
});

app.use("/products", products);
app.use("/cart", cart);
app.use("/checkout", checkout);
app.use("/admin", admin);

app.get("/", ProductsController.listProducts);

app.listen(3000, () => {
console.log("Now listening...");
});
13 changes: 13 additions & 0 deletions config/mongo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"development": {
"database": "project_mimirs_market_development",
"host": "localhost"
},
"test": {
"database": "project_mimirs_market_test",
"host": "localhost"
},
"production": {
"use_env_variable": "MONGO_URL"
}
}
25 changes: 25 additions & 0 deletions config/sequelize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require("dotenv").config();

module.exports = {
development: {
username: process.env.USERNAME,
password: process.env.PASSWORD,
database: "mimirs_market_development",
host: "127.0.0.1",
dialect: "postgres"
},
test: {
username: "root",
password: null,
database: "database_test",
host: "127.0.0.1",
dialect: "mysql"
},
production: {
username: "root",
password: null,
database: "database_production",
host: "127.0.0.1",
dialect: "mysql"
}
};
149 changes: 149 additions & 0 deletions controllers/products.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
const models = require("./../models/sequelize");

module.exports = {
listProducts: (req, res) => {
let productIds = [];

if (req.session.cart) {
productIds = req.session.cart.map(item => {
return Number(item.id);
});
}

let params = {
include: [
{
model: models.Category
}
],
order: [["name", "ASC"]]
};

if (Object.keys(req.query).length) {
params = parseParams(params, req.query);
}

models.Product.findAll(params).then(products => {
products.forEach(product => {
if (productIds.indexOf(product.id) > -1) {
product.inCart = true;
}
});

models.Category.findAll({ order: ["id"] }).then(categories => {
res.render("index", { products, categories });
});
});
},

singleProduct: (req, res) => {
const id = req.params.id;

let productIds = [];

if (req.session.cart) {
productIds = req.session.cart.map(item => {
return Number(item.id);
});
}

models.Product
.findById(id, {
include: [
{
model: models.Category
}
]
})
.then(product => {
if (productIds.indexOf(Number(id)) > -1) {
product.inCart = true;
}
models.Product
.findAll({
where: { categoryId: product.categoryId, id: { $ne: product.id } },
limit: 6,
include: [
{
model: models.Category
}
]
})
.then(relatedProducts => {
relatedProducts.forEach(relatedProduct => {
if (productIds.indexOf(relatedProduct.id) > -1) {
relatedProduct.inCart = true;
}
});
res.render("product", { product, relatedProducts });
});
});
},

showCart: (req, res) => {
let quantities = {};
let productIds = [];

if (req.session.cart) {
productIds = req.session.cart.map(item => {
quantities[item.id] = item.quantity;
return item.id;
});
}

let p = new Promise((resolve, reject) => {
models.Product
.findAll({
include: [
{
model: models.Category
}
],
where: { id: { in: productIds } }
})
.then(products => {
let sum = 0;
products.forEach(product => {
product.total = product.price * quantities[product.id];
sum += product.total;
product.quantity = quantities[product.id];
});

resolve({ products, sum });
});
});

return p;
},

findStates: () => {
return models.State.findAll();
}
};

function parseParams(params, query) {
params.where = {};

if (query.search) {
params.where["$or"] = [
{ name: { $iLike: `%${query.search}%` } },
{ description: { $iLike: `%${query.search}%` } }
];
}

if (query.category.length) {
params.where["categoryId"] = query.category;
}

params.where["price"] = {
$gte: query.minPrice,
$lte: query.maxPrice
};

if (query.sortBy) {
const sort = query.sortBy.split("-");
params.order = [[sort[0], sort[1]]];
}

return params;
}
31 changes: 31 additions & 0 deletions data_structure.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SQL

User
firstName
lastName
email
password
street
city
state

Product
name
sku
description
price
categoryId
inStock

Category
name



// MongoDB

Order
productIds
dateOfTransaction
userId
transactionTotal
44 changes: 44 additions & 0 deletions migrations/sequelize/20170809155632-create-product.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"use strict";
module.exports = {
up: function(queryInterface, Sequelize) {
return queryInterface.createTable("Products", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING
},
sku: {
type: Sequelize.STRING
},
description: {
type: Sequelize.TEXT
},
price: {
type: Sequelize.FLOAT
},
categoryId: {
type: Sequelize.INTEGER
},
inStock: {
type: Sequelize.INTEGER
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn("NOW")
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn("NOW")
}
});
},
down: function(queryInterface, Sequelize) {
return queryInterface.dropTable("Products");
}
};
29 changes: 29 additions & 0 deletions migrations/sequelize/20170809155846-create-category.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"use strict";
module.exports = {
up: function(queryInterface, Sequelize) {
return queryInterface.createTable("Categories", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn("NOW")
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn("NOW")
}
});
},
down: function(queryInterface, Sequelize) {
return queryInterface.dropTable("Categories");
}
};
Loading