From a01c6279e234079f288e0c46b3a100559cf475da Mon Sep 17 00:00:00 2001 From: Ervan Adetya Date: Thu, 1 Mar 2018 11:54:31 +0700 Subject: [PATCH] First Commit --- app.js | 24 ++++++ config/config.json | 23 ++++++ helpers/index.js | 7 ++ .../20180301021910-create-restaurant.js | 30 ++++++++ migrations/20180301021931-create-menu.js | 39 ++++++++++ models/index.js | 36 +++++++++ models/menu.js | 52 +++++++++++++ models/restaurant.js | 12 +++ routes/menus.js | 76 ++++++++++++++++++ routes/restaurants.js | 47 +++++++++++ seeders/20180301022016-SeedingRestaurant.js | 43 +++++++++++ views/menus.ejs | 77 +++++++++++++++++++ views/menusEdit.ejs | 51 ++++++++++++ views/partials/header.ejs | 7 ++ views/restaurants.ejs | 22 ++++++ views/restaurantsMenu.ejs | 47 +++++++++++ 16 files changed, 593 insertions(+) create mode 100644 app.js create mode 100644 config/config.json create mode 100644 helpers/index.js create mode 100644 migrations/20180301021910-create-restaurant.js create mode 100644 migrations/20180301021931-create-menu.js create mode 100644 models/index.js create mode 100644 models/menu.js create mode 100644 models/restaurant.js create mode 100644 routes/menus.js create mode 100644 routes/restaurants.js create mode 100644 seeders/20180301022016-SeedingRestaurant.js create mode 100644 views/menus.ejs create mode 100644 views/menusEdit.ejs create mode 100644 views/partials/header.ejs create mode 100644 views/restaurants.ejs create mode 100644 views/restaurantsMenu.ejs diff --git a/app.js b/app.js new file mode 100644 index 0000000..af060ee --- /dev/null +++ b/app.js @@ -0,0 +1,24 @@ +"use strict" + +const express = require('express'); +const menus = require('./routes/menus'); +const restaurants = require('./routes/restaurants'); +const bodyParser = require('body-parser') + +const app = express(); +app.set('view engine', 'ejs'); +app.use(bodyParser.urlencoded({extended:false})); +app.locals.helpers = require('./helpers') + +const PORT = 3000; + +app.get('/', (req, res) => { + res.send('wow') +}) + +app.use('/menus', menus); +app.use('/restaurants', restaurants) + +app.listen(PORT, () => { + console.log('PORT 3000 successfully running'); +}) \ No newline at end of file diff --git a/config/config.json b/config/config.json new file mode 100644 index 0000000..da42650 --- /dev/null +++ b/config/config.json @@ -0,0 +1,23 @@ +{ + "development": { + "username": "ervan", + "password": "ervan", + "database": "platinum_livecode4", + "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" + } +} diff --git a/helpers/index.js b/helpers/index.js new file mode 100644 index 0000000..c5bbde4 --- /dev/null +++ b/helpers/index.js @@ -0,0 +1,7 @@ +function format_currency(num) { + return `Rp. ${num}` +} + +module.exports = { + format_currency:format_currency +} \ No newline at end of file diff --git a/migrations/20180301021910-create-restaurant.js b/migrations/20180301021910-create-restaurant.js new file mode 100644 index 0000000..b83df0f --- /dev/null +++ b/migrations/20180301021910-create-restaurant.js @@ -0,0 +1,30 @@ +'use strict'; +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Restaurants', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + name: { + type: Sequelize.STRING + }, + address: { + type: Sequelize.STRING + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Restaurants'); + } +}; \ No newline at end of file diff --git a/migrations/20180301021931-create-menu.js b/migrations/20180301021931-create-menu.js new file mode 100644 index 0000000..13f3565 --- /dev/null +++ b/migrations/20180301021931-create-menu.js @@ -0,0 +1,39 @@ +'use strict'; +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Menus', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + name: { + type: Sequelize.STRING + }, + menu_type: { + type: Sequelize.STRING + }, + rating: { + type: Sequelize.INTEGER + }, + price: { + type: Sequelize.INTEGER + }, + RestaurantId: { + type: Sequelize.INTEGER + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Menus'); + } +}; \ No newline at end of file diff --git a/models/index.js b/models/index.js new file mode 100644 index 0000000..5662f10 --- /dev/null +++ b/models/index.js @@ -0,0 +1,36 @@ +'use strict'; + +var fs = require('fs'); +var path = require('path'); +var Sequelize = require('sequelize'); +var basename = path.basename(__filename); +var env = process.env.NODE_ENV || 'development'; +var config = require(__dirname + '/../config/config.json')[env]; +var db = {}; + +if (config.use_env_variable) { + var sequelize = new Sequelize(process.env[config.use_env_variable], config); +} else { + var sequelize = new Sequelize(config.database, config.username, config.password, config); +} + +fs + .readdirSync(__dirname) + .filter(file => { + return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); + }) + .forEach(file => { + var model = sequelize['import'](path.join(__dirname, file)); + db[model.name] = model; + }); + +Object.keys(db).forEach(modelName => { + if (db[modelName].associate) { + db[modelName].associate(db); + } +}); + +db.sequelize = sequelize; +db.Sequelize = Sequelize; + +module.exports = db; diff --git a/models/menu.js b/models/menu.js new file mode 100644 index 0000000..f299dfd --- /dev/null +++ b/models/menu.js @@ -0,0 +1,52 @@ +'use strict'; +module.exports = (sequelize, DataTypes) => { + var Menu = sequelize.define('Menu', { + name: DataTypes.STRING, + menu_type: { + type:DataTypes.STRING, + validate: { + isIn: { + args:[['food', 'drink']], + msg: "Isi menu type dengan food/drink" + } + } + }, + rating: DataTypes.INTEGER, + price: DataTypes.INTEGER, + RestaurantId: DataTypes.INTEGER + }, { + // validate: { + // notMoreThan5(next) { + // Menu.findAll({ + // include: [{model: sequelize.models.Restaurant}], + // where: { + // RestaurantId: this.RestaurantId, + // menu_type: this.menu_type + // } + // }) + // .then(data =>{ + // if(data.length>=5) { + // next(`${this.Restaurant.name} telah memiliki 5 menu yang type nya ${this.menu_type}`) + // } + // }) + // } + // }, + hooks: { + beforeValidate: (instance, options) => { + if(instance.price<1) { + if(instance.menu_type === "food") { + instance.price = 15000; + } + else if(instance.menu_type === "drink") { + instance.price = 10000; + } + } + } + } + }); + Menu.associate = function(models) { + // associations can be defined here + Menu.belongsTo(models.Restaurant) + }; + return Menu; +}; \ No newline at end of file diff --git a/models/restaurant.js b/models/restaurant.js new file mode 100644 index 0000000..f5e14c6 --- /dev/null +++ b/models/restaurant.js @@ -0,0 +1,12 @@ +'use strict'; +module.exports = (sequelize, DataTypes) => { + var Restaurant = sequelize.define('Restaurant', { + name: DataTypes.STRING, + address: DataTypes.STRING + }, {} +); + Restaurant.associate = function(models) { + Restaurant.hasMany(models.Menu) + }; + return Restaurant; +}; \ No newline at end of file diff --git a/routes/menus.js b/routes/menus.js new file mode 100644 index 0000000..7a307e8 --- /dev/null +++ b/routes/menus.js @@ -0,0 +1,76 @@ +const express = require('express'); +const model = require('../models') + +const menus = express.Router(); + +menus.get('/', (req, res) => { + let err = req.query.err; + model.Menu.findAll({ + include: [{model: model.Restaurant}], + order: [['id','ASC']] + }) + .then(menus => { + model.Restaurant.findAll() + .then(restaurants => { + res.render('menus', {menus:menus, restaurants:restaurants, err:err}); + }) + }); +}); + +menus.post('/', (req, res) => { + let record = { + name: req.body.name, + menu_type: req.body.menu_type, + rating: req.body.rating, + price: req.body.price, + RestaurantId: req.body.RestaurantId + }; + model.Menu.create(record) + .then(() => { + res.redirect('/menus') + }) + .catch(err => { + res.redirect(`/menus?err=${err}`) + }); +}); + +menus.get('/:id/delete', (req, res) => { + let id = req.params.id; + model.Menu.destroy({where: {id:id}}) + .then(() => { + res.redirect('/menus') + }) + .catch(err => console.log(err)); + +}) + +menus.get('/:id/edit', (req, res) => { + let id = req.params.id; + let err = req.query.err; + model.Menu.findById(id) + .then(menu => { + model.Restaurant.findAll() + .then(restaurants => { + res.render('menusEdit', {menu:menu, restaurants:restaurants, err:err}); + }) + }); +}); +menus.post('/:id/edit', (req, res) => { + let id = req.params.id; + let updatedRecord = { + name: req.body.name, + menu_type: req.body.menu_type, + rating: req.body.rating, + price: req.body.price, + RestaurantId: req.body.RestaurantId + }; + model.Menu.update(updatedRecord, {where: {id:id}}) + .then(() => { + res.redirect('/menus'); + }) + .catch(err => { + res.redirect(`/menus/${id}/edit?err=${err}`) + }); +}) + +module.exports = menus; \ No newline at end of file diff --git a/routes/restaurants.js b/routes/restaurants.js new file mode 100644 index 0000000..b60c5ad --- /dev/null +++ b/routes/restaurants.js @@ -0,0 +1,47 @@ +"use strict" +const express = require('express'); +const model = require('../models'); +const Sequelize = require('sequelize'); +const Op = Sequelize.Op + + +const restaurants = express.Router(); + +restaurants.get('/', (req, res) => { + model.Restaurant.findAll() + .then(data => { + res.render('restaurants', {restaurants: data}) + }) + .catch(err => console.log(err)) +}); + +restaurants.get('/:id/view_menu', (req, res) => { + let id = req.params.id; + let type = req.query.order + let name = req.query.name + model.Menu.findAll({ + where:{ + [type]: { + [Op.iLike]: `%${name}%` + } + }, + order: [[`id`,'ASC']] + }) + .then(menus => { + model.Restaurant.findById(id) + .then(restaurant => { + res.render('restaurantsMenu', {restaurant:restaurant, menus:menus}) + }) + }) + // res.send(id) +}) + +restaurants.post('/:id/view_menu', (req, res) => { + let id = req.params.id + let order = req.body.orderBy + let name = req.body.name + //view_menu?order=req.body.order + res.redirect(`/restaurants/${id}/view_menu?order=${order}&name=${name}`) +}) + +module.exports = restaurants; \ No newline at end of file diff --git a/seeders/20180301022016-SeedingRestaurant.js b/seeders/20180301022016-SeedingRestaurant.js new file mode 100644 index 0000000..d34bfad --- /dev/null +++ b/seeders/20180301022016-SeedingRestaurant.js @@ -0,0 +1,43 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.bulkInsert('Person', [{ + name: 'John Doe', + isBetaMember: false + }], {}); + */ + return queryInterface.bulkInsert('Restaurants', [ + { + name: 'Rocky', + address: 'Jalan U, depan BINUS Syahdan', + createdAt: new Date, + updatedAt: new Date}, + { + name: 'Super Sambal', + address: 'GreenVille', + createdAt: new Date, + updatedAt: new Date}, + { + name: 'Kintan Buffet', + address: 'Central Park Mall', + createdAt: new Date, + updatedAt: new Date} + ]) + }, + + down: (queryInterface, Sequelize) => { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.bulkDelete('Person', null, {}); + */ + } +}; diff --git a/views/menus.ejs b/views/menus.ejs new file mode 100644 index 0000000..eba436a --- /dev/null +++ b/views/menus.ejs @@ -0,0 +1,77 @@ + + +
+

Menus

+
+ +
+ + + + + + + + + + + <%menus.forEach(menu => {%> + + + + + + + + + + + <%})%> +

Id

Name

Menu Type

Rating

Price

Restaurant ID

Action

<%=menu.id%>

<%=menu.name%>

<%=menu.menu_type%>

<%=menu.rating%>

<%=helpers.format_currency(menu.price)%>

<%=menu.Restaurant.name%>

Edit

Delete

+
+ +
+
+ + + + +
<%=err%>
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name:
Menu Type:
Rating:
Price:
Restaurant: + +
+
+
\ No newline at end of file diff --git a/views/menusEdit.ejs b/views/menusEdit.ejs new file mode 100644 index 0000000..f1a9d63 --- /dev/null +++ b/views/menusEdit.ejs @@ -0,0 +1,51 @@ + + +
+

Menus Edit

+
+ +
+
+ + + + +
<%=err%>
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name:
Menu Type:
Rating:
Price:
Restaurant: + +
+
+
\ No newline at end of file diff --git a/views/partials/header.ejs b/views/partials/header.ejs new file mode 100644 index 0000000..434ed48 --- /dev/null +++ b/views/partials/header.ejs @@ -0,0 +1,7 @@ +
+ + + + +
+
\ No newline at end of file diff --git a/views/restaurants.ejs b/views/restaurants.ejs new file mode 100644 index 0000000..ee1133a --- /dev/null +++ b/views/restaurants.ejs @@ -0,0 +1,22 @@ +
+

Restaurants

+
+ +
+ + + + + + + + <%restaurants.forEach(restaurant => {%> + + + + + + + <%})%> +

Id

Name

Address

Action

<%=restaurant.id%>

<%=restaurant.name%>

<%=restaurant.address%>

View Menu

+
\ No newline at end of file diff --git a/views/restaurantsMenu.ejs b/views/restaurantsMenu.ejs new file mode 100644 index 0000000..2abf7b6 --- /dev/null +++ b/views/restaurantsMenu.ejs @@ -0,0 +1,47 @@ + + +
+

Menu Restaurant: <%=restaurant.name%>

+
+ +
+
+ + + + + + + + + + +

Search by:

Keyword :

+
+
+ +
+ + + + + + + + + <%menus.forEach(menu => {%> + + + + + + + + <%})%> +

Id

Name

Menu Type

Rating

Price

<%=menu.id%>

<%=menu.name%>

<%=menu.menu_type%>

<%=menu.rating%>

<%=helpers.format_currency(menu.price)%>

+
\ No newline at end of file