diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/app.js b/app.js new file mode 100644 index 0000000..812281e --- /dev/null +++ b/app.js @@ -0,0 +1,18 @@ +const express = require('express'); +const Sequelize = require('sequelize'); +const bodyParser = require('body-parser'); +const models = require('./models'); +const app = express(); + +app.set('view engine', 'ejs'); +app.use(bodyParser.urlencoded({ extended: false })) +app.use(bodyParser.json()) +app.locals.helper = require('./helper/') + +const menu = require('./routes/menu.js'); +const restaurant = require('./routes/restaurant.js') + +app.use('/menus', menu); +app.use('/restaurants', restaurant); + +app.listen(3000, console.log('AYE AYE CAPTAIN!')) diff --git a/config/config.json b/config/config.json new file mode 100644 index 0000000..7e9772e --- /dev/null +++ b/config/config.json @@ -0,0 +1,23 @@ +{ + "development": { + "username": "devdots", + "password": "Semau6ue", + "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/helper/index.js b/helper/index.js new file mode 100644 index 0000000..8d44c42 --- /dev/null +++ b/helper/index.js @@ -0,0 +1,6 @@ +function ubahAgka(angka) { + angka = angka.toLocaleString() + return `Rp. ${angka}` +} + +module.exports = {ubahAgka} diff --git a/migrations/20180301021445-create-restaurant.js b/migrations/20180301021445-create-restaurant.js new file mode 100644 index 0000000..b83df0f --- /dev/null +++ b/migrations/20180301021445-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/20180301021649-create-menu.js b/migrations/20180301021649-create-menu.js new file mode 100644 index 0000000..477aedb --- /dev/null +++ b/migrations/20180301021649-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 + }, + id_restaurant: { + 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..aa40902 --- /dev/null +++ b/models/menu.js @@ -0,0 +1,45 @@ +'use strict'; +module.exports = (sequelize, DataTypes) => { + var Menu = sequelize.define('Menu', { + name: DataTypes.STRING, + menu_type: { + type: DataTypes.STRING, + validate: { + is: { + args: /(food|drink)/, + msg: 'Isi menu type dengan food / drink' + } + } + }, + rating: DataTypes.INTEGER, + price: DataTypes.INTEGER, + id_restaurant: DataTypes.INTEGER + }, { + hooks: { + beforeCreate: (menu, options) => { + if (menu.menu_type == 'food' && menu.price == 0) { + menu.price = 15000 + } + else if (menu.menu_type == 'drink' && menu.price == 0) { + menu.price = 10000 + } + }, + beforeUpdate: (instance, options) => { + if (instance.menu_type == 'food' && instance.price === '0') { + instance.price = 15000 + } + else if (instance.menu_type == 'drink' && instance.price === '0') { + instance.price = 10000 + } + } + } + + }); + Menu.associate = function(models) { + // associations can be defined here + Menu.belongsTo(models.Restaurant, { + foreignKey: 'id_restaurant' + }) + }; + return Menu; +}; diff --git a/models/restaurant.js b/models/restaurant.js new file mode 100644 index 0000000..2ce3459 --- /dev/null +++ b/models/restaurant.js @@ -0,0 +1,14 @@ +'use strict'; +module.exports = (sequelize, DataTypes) => { + var Restaurant = sequelize.define('Restaurant', { + name: DataTypes.STRING, + address: DataTypes.STRING + }, {}); + Restaurant.associate = function(models) { + // associations can be defined here + Restaurant.hasMany(models.Menu, { + foreignKey: 'id_restaurant' + }) + }; + return Restaurant; +}; diff --git a/package.json b/package.json index f15ec6e..8aab187 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express-sequelize-final", "version": "1.0.0", - "description": "", + "description": "## Challenge 1", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" @@ -14,5 +14,13 @@ "express": "^4.16.2", "pg": "^7.4.1", "sequelize": "^4.34.1" - } + }, + "repository": { + "type": "git", + "url": "git+https://github.com/platinum-fox-2017/livecode4.git" + }, + "bugs": { + "url": "https://github.com/platinum-fox-2017/livecode4/issues" + }, + "homepage": "https://github.com/platinum-fox-2017/livecode4#readme" } diff --git a/routes/menu.js b/routes/menu.js new file mode 100644 index 0000000..3e76e1b --- /dev/null +++ b/routes/menu.js @@ -0,0 +1,78 @@ +const express = require('express'); +const router = express.Router() +const models = require('../models') + +router.get('/', function (req, res) { + models.Menu.findAll({ + order: ['id'], + include:[{ + model: models.Restaurant + }] + }).then(data => { + models.Restaurant.findAll().then(data1 => { + let test = JSON.parse(JSON.stringify(data)) + console.log(test); + res.render('menu', {data_menu: data, data_rest: data1}) + }) + }) +}) + +router.post('/add', function (req, res) { + let obj = { + name: req.body.name, + menu_type: req.body.menu_type, + rating: req.body.rating, + price: req.body.price, + id_restaurant: req.body.id_restaurant + } + // console.log(obj); + models.Menu.create(obj).then(data => { + res.redirect('/menus') + }) +}) + +router.get('/edit/:id', function (req, res) { + // console.log(typeof req.params.id); + let numMenu = +req.params.id + models.Menu.findById(numMenu).then(data => { + models.Restaurant.findAll().then(data1 => { + let test = JSON.parse(JSON.stringify(data)) + + console.log(test); + res.render('edit-menu', {data_menu: data, data_rest: data1}) + }) + }) +}) + +router.post('/edit/:id', function (req, res) { + let obj = { + name: req.body.name, + menu_type: req.body.menu_type, + rating: req.body.rating, + price: req.body.price, + id_restaurant: req.body.id_restaurant + } + models.Menu.update(obj, { + where: { + id: req.params.id + } + }).then(data => { + res.redirect('/menus') + }) +}) + +router.get('/delete/:id', function (req, res) { + models.Menu.destroy({ + where: { + id: req.params.id + } + }).then(data => { + res.redirect('/menus') + }) +}) + + + + + +module.exports = router diff --git a/routes/restaurant.js b/routes/restaurant.js new file mode 100644 index 0000000..87ffbc8 --- /dev/null +++ b/routes/restaurant.js @@ -0,0 +1,32 @@ +const express = require('express'); +const router = express.Router() +const models = require('../models') + +router.get('/', function (req, res) { + models.Restaurant.findAll({ + include: { + model: models.Menu + } + }).then(data => { + let test = JSON.parse(JSON.stringify(data)) + console.log(test); + res.render('restaurant', {data_rest: data}) + }) +}) + +router.get('/:id/view_menu', function (req, res) { + models.Restaurant.findById(req.params.id,{ + include: { + model: models.Menu + } + }).then(data => { + let test = JSON.parse(JSON.stringify(data)) + console.log(test); + console.log(Object.keys(test.Menus[0])); + res.render('menu-restaurant', {data_rest: data}) + }) +}) + + + +module.exports = router diff --git a/seeders/20180301021804-add-restaurant.js b/seeders/20180301021804-add-restaurant.js new file mode 100644 index 0000000..a1725b8 --- /dev/null +++ b/seeders/20180301021804-add-restaurant.js @@ -0,0 +1,40 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + */ + return queryInterface.bulkInsert('Restaurants', [ + { + name: 'Hanamasa', + address: 'suatu jalan di jakarta', + createdAt: new Date(), + updatedAt: new Date() + },{ + name: 'KFC', + address: 'suatu jalan di bogor', + createdAt: new Date(), + updatedAt: new Date() + },{ + name: 'MCD', + address: 'suatu jalan di bandung', + createdAt: new Date(), + updatedAt: new Date() + } + ], {}); + }, + + down: (queryInterface, Sequelize) => { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + + Example: + */ + return queryInterface.bulkDelete('Restaurants', null, {}); + } +}; diff --git a/seeders/20180301022946-add-menu.js b/seeders/20180301022946-add-menu.js new file mode 100644 index 0000000..c916769 --- /dev/null +++ b/seeders/20180301022946-add-menu.js @@ -0,0 +1,49 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + */ + return queryInterface.bulkInsert('Menus', [ + { + name: 'Beef Teriyaki', + menu_type: 'food', + rating: 7, + price: 45000, + id_restaurant: 1, + createdAt: new Date(), + updatedAt: new Date() + },{ + name: 'Grilled Chicken', + menu_type: 'food', + rating: 9, + price: 40000, + id_restaurant: 2, + createdAt: new Date(), + updatedAt: new Date() + },{ + name: 'Beef Teriyaki', + menu_type: 'food', + rating: 7, + price: 45000, + id_restaurant: 3, + createdAt: new Date(), + updatedAt: new Date() + }, + ], {}); + }, + + down: (queryInterface, Sequelize) => { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + + Example: + */ + return queryInterface.bulkDelete('Menus', null, {}); + } +}; diff --git a/views/edit-menu.ejs b/views/edit-menu.ejs new file mode 100644 index 0000000..cc0dca1 --- /dev/null +++ b/views/edit-menu.ejs @@ -0,0 +1,48 @@ + + + + + Edit User + + + + + + + +
+

Edit Data User

+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + Cancel +
+
+ + diff --git a/views/menu-restaurant.ejs b/views/menu-restaurant.ejs new file mode 100644 index 0000000..a593724 --- /dev/null +++ b/views/menu-restaurant.ejs @@ -0,0 +1,46 @@ + + + + + + + + + + +

Menu Restaurant : <%=data_rest.name%>

+
+
+ + +
+
+ + + + + + + + + + + <%data_rest.Menus.forEach((data, i) =>{%> + + + + + + + + <%})%> + + +
IdNameMenu TypeRatingPrice
<%=i+1%><%=data.name%><%=data.menu_type%><%=data.rating%><%= helper.ubahAgka(data.price)%>
+ + diff --git a/views/menu.ejs b/views/menu.ejs new file mode 100644 index 0000000..5022174 --- /dev/null +++ b/views/menu.ejs @@ -0,0 +1,82 @@ + + + + + + + + +
+
+

List Menu

+
+
+
+ + + + + + + + + + + + + <%data_menu.forEach((data, i) =>{%> + + + + + + + + + + <%})%> + + +
IdNameMenu TypeRatingPriceRestauran IDAction
<%=i+1%><%=data.name%><%=data.menu_type%><%=data.rating%><%= helper.ubahAgka(data.price) %><%=data.Restaurant.name%> + Edit + Delete +
+ +
+

Add new Menu

+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + Cancel +
+
+ + + diff --git a/views/restaurant.ejs b/views/restaurant.ejs new file mode 100644 index 0000000..9b655fd --- /dev/null +++ b/views/restaurant.ejs @@ -0,0 +1,39 @@ + + + + + + + + +
+
+

List Restaurant

+
+
+
+ + + + + + + + + + <%data_rest.forEach((data, i) =>{%> + + + + + + + <%})%> + + +
IdNameAddressAction
<%=i+1%><%=data.name%><%=data.address%> + View Menu +
+ +