Skip to content
Open

R02 #2030

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
fca7f3b
feat: add R01.test.js and unit-test-helpers.js
Carrot7712 Jan 13, 2022
7ece79e
add R01.test.js && unit-test-helper.js
AmberYen Mar 2, 2022
b54a2e9
add R02.test.js file
AmberYen Mar 2, 2022
79ff158
註解 typo 修正
zjzheng17 Jul 18, 2022
9d566b6
correcting typo in comment
zjzheng17 Jul 18, 2022
03c14c0
correcting typo in comment
zjzheng17 Jul 18, 2022
b53b8df
feat: add handlebars
Sunnylin0320 Sep 12, 2023
c4156a4
feat: add index page
Sunnylin0320 Sep 12, 2023
8487e9a
feat: add admin index page
Sunnylin0320 Sep 14, 2023
07e3f4a
feat: add user model
Sunnylin0320 Sep 14, 2023
705f72e
feat: user signup
Sunnylin0320 Sep 14, 2023
bc142a7
feat: flash msg & signup verification
Sunnylin0320 Sep 19, 2023
b9040cc
feat: passport init & signin
Sunnylin0320 Sep 19, 2023
2dfd00e
feat: add header & footer
Sunnylin0320 Sep 19, 2023
085cc7b
feat: user model add is_admin
Sunnylin0320 Sep 19, 2023
e980369
feat: add restaurant model
Sunnylin0320 Sep 19, 2023
5eb1fe4
feat: modify admin restaurants page
Sunnylin0320 Sep 19, 2023
e0ebb95
feat: create restaurant
Sunnylin0320 Sep 20, 2023
d0bb4f5
feat: admin restaurant page
Sunnylin0320 Sep 20, 2023
6b504c1
feat: admin update restaurant
Sunnylin0320 Sep 20, 2023
151f4a0
feat: delete restaurant
Sunnylin0320 Sep 20, 2023
92d1d24
feat: add restaurant image
Sunnylin0320 Sep 20, 2023
65bbbfc
feat: add seed data
Sunnylin0320 Sep 21, 2023
1e4a89f
feat: modify config for heroku
Sunnylin0320 Sep 25, 2023
d04bd47
feat: modify config for heroku
Sunnylin0320 Sep 25, 2023
69ec77c
feat: modify config for heroku
Sunnylin0320 Sep 26, 2023
823bef4
feat: add imgur api
Sunnylin0320 Sep 26, 2023
1c67141
Merge remote-tracking branch 'origin/R01-test' into R01
Sunnylin0320 Sep 27, 2023
9565fd2
R01
Sunnylin0320 Oct 2, 2023
4057158
feat: add category model
Sunnylin0320 Oct 3, 2023
48a5984
feat: update seed files
Sunnylin0320 Oct 3, 2023
c600c45
feat: show category on admin restaurant pages
Sunnylin0320 Oct 3, 2023
70bff5a
feat: add categories selector on admin create and edit page
Sunnylin0320 Oct 3, 2023
8b3f21a
feat: add ifCond hbs helper & update category selector
Sunnylin0320 Oct 3, 2023
819638b
feat: add admin categories page
Sunnylin0320 Oct 4, 2023
83a0ba7
feat: category create
Sunnylin0320 Oct 4, 2023
49446be
feat: category update
Sunnylin0320 Oct 4, 2023
6bf8131
feat: category delete
Sunnylin0320 Oct 4, 2023
baab76a
feat: add restaurant page
Sunnylin0320 Oct 4, 2023
d222303
R02
Sunnylin0320 Oct 7, 2023
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
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
IMGUR_CLIENT_ID=
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: NODE_ENV=production node app.js
41 changes: 41 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,50 @@
const path = require('path')
const express = require('express')
const handlebars = require('express-handlebars') // 引入 express-handlebars
const flash = require('connect-flash')
const methodOverride = require('method-override')
const session = require('express-session')
const passport = require('./config/passport')
const handlebarsHelpers = require('./helpers/handlebars-helpers')
const { getUser } = require('./helpers/auth-helpers')
const routes = require('./routes')

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

const app = express()
const port = process.env.PORT || 3000
const SESSION_SECRET = 'secret'
app.engine(
'hbs',
handlebars({
extname: '.hbs',
helpers: {
...handlebarsHelpers,
eq: function (a, b) {
return a === b
}
}
})
)
app.set('view engine', 'hbs')
app.use(express.urlencoded({ extended: true }))
app.use(
session({ secret: SESSION_SECRET, resave: false, saveUninitialized: false })
)
app.use(passport.initialize())
app.use(passport.session())
app.use(flash())
app.use(methodOverride('_method'))
app.use('/upload', express.static(path.join(__dirname, 'upload')))

app.use((req, res, next) => {
res.locals.success_messages = req.flash('success_messages')
res.locals.error_messages = req.flash('error_messages')
res.locals.user = getUser(req)
next()
})
app.use(routes)

app.listen(port, () => {
Expand Down
6 changes: 1 addition & 5 deletions config/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@
"dialect": "mysql"
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
"use_env_variable": "MYSQL_DATABASE_URL"
},
"travis": {
"username": "travis",
Expand Down
55 changes: 55 additions & 0 deletions config/passport.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const passport = require('passport')
const LocalStrategy = require('passport-local')
const bcrypt = require('bcryptjs')
const db = require('../models')
const User = db.User

// setup passport strategy
passport.use(
new LocalStrategy(
// customize user field
{
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
// authenticate user
(req, email, password, cb) => {
User.findOne({ where: { email } }).then(user => {
if (!user) {
return cb(
null,
false,
req.flash('error_messages', '帳號或密碼輸入錯誤!')
)
}

bcrypt.compare(password, user.password).then(res => {
if (!res) {
return cb(
null,
false,
req.flash('error_messages', '帳號或密碼輸入錯誤!')
)
}

return cb(null, user)
})
})
}
)
)

// serialize and deserialize user
passport.serializeUser((user, cb) => {
cb(null, user.id)
})
passport.deserializeUser((id, cb) => {
User.findByPk(id).then(user => {
user = user.toJSON() // 加入這行
console.log(user)
return cb(null, user)
})
})

module.exports = passport
138 changes: 138 additions & 0 deletions controllers/admin-controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
const { Restaurant, User, Category } = require('../models')
const { imgurFileHandler } = require('../helpers/file-helpers')

const adminController = {
getRestaurants: (req, res, next) => {
Restaurant.findAll({
raw: true,
nest: true,
include: [Category]
})
.then(restaurants => res.render('admin/restaurants', { restaurants }))
.catch(err => next(err))
},
createRestaurant: (req, res, next) => {
return Category.findAll({
raw: true
})
.then(categories =>
res.render('admin/create-restaurant', { categories })
)
.catch(err => next(err))
},
postRestaurant: (req, res, next) => {
const { name, tel, address, openingHours, description, categoryId } =
req.body
if (!name) throw new Error('Restaurant name is required!')

const { file } = req

imgurFileHandler(file)
.then(filePath =>
Restaurant.create({
name,
tel,
address,
openingHours,
description,
image: filePath || null,
categoryId
})
)
.then(() => {
req.flash('success_messages', 'restaurant was successfully created')
res.redirect('/admin/restaurants')
})
.catch(err => next(err))
},
getRestaurant: (req, res, next) => {
Restaurant.findByPk(req.params.id, {
raw: true,
nest: true,
include: [Category]
})
.then(restaurant => {
if (!restaurant) throw new Error("Restaurant didn't exist!")

res.render('admin/restaurant', { restaurant })
})
.catch(err => next(err))
},
editRestaurant: (req, res, next) => {
return Promise.all([
Restaurant.findByPk(req.params.id, { raw: true }),
Category.findAll({ raw: true })
])
.then(([restaurant, categories]) => {
if (!restaurant) throw new Error("Restaurant doesn't exist!")
res.render('admin/edit-restaurant', { restaurant, categories })
})
.catch(err => next(err))
},
putRestaurant: (req, res, next) => {
const { name, tel, address, openingHours, description, categoryId } =
req.body
if (!name) throw new Error('Restaurant name is required!')

const { file } = req

Promise.all([Restaurant.findByPk(req.params.id), imgurFileHandler(file)])
.then(([restaurant, filePath]) => {
if (!restaurant) throw new Error("Restaurant didn't exist!")

return restaurant.update({
name,
tel,
address,
openingHours,
description,
image: filePath || restaurant.image,
categoryId
})
})
.then(() => {
req.flash('success_messages', 'restaurant was successfully to update')
res.redirect('/admin/restaurants')
})
.catch(err => next(err))
},
deleteRestaurant: (req, res, next) => {
return Restaurant.findByPk(req.params.id)
.then(restaurant => {
if (!restaurant) throw new Error("Restaurant didn't exist!")

return restaurant.destroy()
})
.then(() => res.redirect('/admin/restaurants'))
.catch(err => next(err))
},
getUsers: (req, res, next) => {
return User.findAll({
raw: true
})
.then(users => {
res.render('admin/users', { users })
})
.catch(err => next(err))
},
patchUser: (req, res, next) => {
return User.findByPk(req.params.id)
.then(user => {
if (user.email === 'root@example.com') {
req.flash('error_messages', '禁止變更 root 權限')
throw res.redirect('back')
}
return user
})
.then(user => user.update({ isAdmin: !user.isAdmin }))
.then(() => {
req.flash('success_messages', '使用者權限變更成功')
res.redirect('/admin/users')
})
.catch(err => {
next(err)
})
}
}

module.exports = adminController
51 changes: 51 additions & 0 deletions controllers/category-controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
const { Category } = require('../models')

const categoryController = {
getCategories: (req, res, next) => {
return Promise.all([
Category.findAll({ raw: true }),
req.params.id ? Category.findByPk(req.params.id, { raw: true }) : null
])
.then(([categories, category]) => {
res.render('admin/categories', {
categories,
category
})
})
.catch(err => next(err))
},
postCategory: (req, res, next) => {
const { name } = req.body

if (!name) throw new Error('Category name is required!')

return Category.create({ name })
.then(() => res.redirect('/admin/categories'))
.catch(err => next(err))
},
putCategory: (req, res, next) => {
const { name } = req.body

if (!name) throw new Error('Category name is required!')

return Category.findByPk(req.params.id)
.then(category => {
if (!category) throw new Error("Category doesn't exist!")

return category.update({ name })
})
.then(() => res.redirect('/admin/categories'))
.catch(err => next(err))
},
deleteCategory: (req, res, next) => {
return Category.findByPk(req.params.id)
.then(category => {
if (!category) throw new Error("Category didn't exist!") // 反查,確認要刪除的類別存在,再進行下面刪除動作

return category.destroy()
})
.then(() => res.redirect('/admin/categories'))
.catch(err => next(err))
}
}
module.exports = categoryController
50 changes: 50 additions & 0 deletions controllers/restaurant-controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const { Restaurant, Category } = require('../models')
const restaurantController = {
getRestaurants: (req, res) => {
return Restaurant.findAll({
include: Category,
nest: true,
raw: true
}).then(restaurants => {
const data = restaurants.map(r => ({
...r,
description: r.description.substring(0, 50)
}))
return res.render('restaurants', {
restaurants: data
})
})
},
getRestaurant: (req, res, next) => {
return Restaurant.findByPk(req.params.id, {
include: Category
})
.then(restaurant => {
if (!restaurant) throw new Error("Restaurant didn't exist!")

return restaurant.increment('viewCount')
})
.then(restaurant => {
res.render('restaurant', {
restaurant: restaurant.toJSON()
})
})
.catch(err => next(err))
},
getDashboard: (req, res, next) => {
return Restaurant.findByPk(req.params.id, {
include: Category,
nest: true,
raw: true
})
.then(restaurant => {
if (!restaurant) throw new Error("Restaurant didn't exist!")

res.render('dashboard', { restaurant })
})
.catch(err => next(err))
}

}

module.exports = restaurantController
Loading