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
+
+
+
+
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%>
+
+
+
+
+ Id |
+ Name |
+ Menu Type |
+ Rating |
+ Price |
+
+
+ <%data_rest.Menus.forEach((data, i) =>{%>
+
+ <%=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
+
+
+
+
+
+
+ Id |
+ Name |
+ Menu Type |
+ Rating |
+ Price |
+ Restauran ID |
+ Action |
+
+
+ <%data_menu.forEach((data, i) =>{%>
+
+ <%=i+1%> |
+ <%=data.name%> |
+ <%=data.menu_type%> |
+ <%=data.rating%> |
+ <%= helper.ubahAgka(data.price) %> |
+ <%=data.Restaurant.name%> |
+
+ Edit
+ Delete
+ |
+
+ <%})%>
+
+
+
+
+
+ Add new Menu
+
+
+
+
+
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
+
+
+
+
+
+
+ Id |
+ Name |
+ Address |
+ Action |
+
+
+ <%data_rest.forEach((data, i) =>{%>
+
+ <%=i+1%> |
+ <%=data.name%> |
+ <%=data.address%> |
+
+ View Menu
+ |
+
+ <%})%>
+
+
+
+
+