Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 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
96da4be
feat:add R02.test.js
Carrot7712 Jan 13, 2022
37322b4
feat:add R03.test.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
ef44c3e
add R03.test.js file
AmberYen Mar 2, 2022
1ead393
add R04.test.js
AmberYen Mar 2, 2022
79ff158
註解 typo 修正
zjzheng17 Jul 18, 2022
9d566b6
correcting typo in comment
zjzheng17 Jul 18, 2022
4fe60b0
correcting typo in comment
zjzheng17 Jul 18, 2022
03c14c0
correcting typo in comment
zjzheng17 Jul 18, 2022
326bed8
fix R01.test.js comment typo
tuterwell Aug 10, 2023
d5b1553
chore: init github workflow
eugenechen0514 Sep 9, 2023
6f29ed3
chore: init github workflow
eugenechen0514 Sep 9, 2023
02a746f
chore: init github workflow
eugenechen0514 Sep 9, 2023
16bd368
chore: init github workflow
eugenechen0514 Sep 9, 2023
fe01b7f
Update unit-test-helper.js
tuterwell Sep 12, 2023
13c29eb
Update unit-test-helper.js update()
tuterwell Sep 12, 2023
e2665da
chore: format code
eugenechen0514 Sep 17, 2023
1be932b
test: fix update method
eugenechen0514 Sep 17, 2023
d12a942
Merge commit '1be932b9d1998168679d2cdf5a7a9e2f1d2bca91' into R01-test
eugenechen0514 Sep 17, 2023
20ab723
Merge branch 'R01-test' into R02-test
eugenechen0514 Sep 17, 2023
fa173a7
chore: fix code format
eugenechen0514 Sep 17, 2023
12487dc
Merge branch 'R02-test' into R03-test
eugenechen0514 Sep 17, 2023
2942b99
Merge branch 'R03-test' into R04-test
eugenechen0514 Sep 17, 2023
1b8cd24
Delete .travis.yml
tuterwell Sep 18, 2023
f3b0c32
Delete .travis.yml
tuterwell Sep 18, 2023
a449027
Delete .travis.yml
tuterwell Sep 18, 2023
c26e8ee
Delete .travis.yml
tuterwell Sep 18, 2023
3f6b855
feat: add handlebars
maomao0007 Jun 27, 2024
b24885e
feat: add index page
maomao0007 Jun 27, 2024
0715003
feat: add admin index page
maomao0007 Jun 27, 2024
043241c
feat: add user model
maomao0007 Jun 28, 2024
27b2d5c
feat: user signup
maomao0007 Jun 28, 2024
89cd7b5
feat: flash msg & signup verification
maomao0007 Jun 28, 2024
60f2bb0
feat: passport init & signin
maomao0007 Jun 28, 2024
4739e14
feat: add header & footer
maomao0007 Jun 28, 2024
0bcbc51
feat: user model add is_admin
maomao0007 Jun 28, 2024
ae800e7
feat: add restaurant model
maomao0007 Jun 28, 2024
d26ff04
feat: modify admin restaurants page
maomao0007 Jun 28, 2024
dfa657b
feat: create restaurant
maomao0007 Jun 28, 2024
9f75410
feat: admin restaurant page
maomao0007 Jun 28, 2024
04e51f7
feat: admin update restaurant
maomao0007 Jun 28, 2024
d2ca57d
feat: delete restaurant
maomao0007 Jun 28, 2024
2c0f403
feat: add restaurant image
maomao0007 Jun 30, 2024
2ddebce
fix commit
maomao0007 Jun 30, 2024
ae9e430
Import test file.
maomao0007 Jun 30, 2024
bc7da3a
Modify the functionality of the postRestaurant feature.
maomao0007 Jun 30, 2024
f7cb13f
Modify the functionality of postRestaurant feature.
maomao0007 Jun 30, 2024
3fd657d
Add a user role page.
maomao0007 Jul 1, 2024
aa63382
Add a User role page.
maomao0007 Jul 1, 2024
5b28288
Add a user role page.
maomao0007 Jul 2, 2024
96938fe
feat: add category model
maomao0007 Jul 2, 2024
df4190e
feat: update seed files
maomao0007 Jul 2, 2024
732a729
CommitProject Repo
maomao0007 Jul 2, 2024
e84843c
feat: add categories selector on admin create and edit page
maomao0007 Jul 2, 2024
0d0e76a
feat: add ifCond hbs helper & update category selector
maomao0007 Jul 2, 2024
5771034
feat: add ifCond hbs helper & update category selector
maomao0007 Jul 2, 2024
afa5a0d
feat: add admin categories page
maomao0007 Jul 3, 2024
157248e
feat: category create
maomao0007 Jul 3, 2024
07e67da
feat: category update
maomao0007 Jul 3, 2024
d2f3b9a
feat: category update
maomao0007 Jul 3, 2024
2ad63e9
feat: category update
maomao0007 Jul 3, 2024
b55af8d
feat: category delete
maomao0007 Jul 3, 2024
1f60843
feat: add restaurants index page
maomao0007 Jul 3, 2024
029d98f
feat: add restaurant page
maomao0007 Jul 4, 2024
dc0a1ca
Merge remote-tracking branch 'origin/R02-test' into R02
maomao0007 Jul 4, 2024
94e71ad
Add the restaurant dashboard page and implement the view count feature.
maomao0007 Jul 4, 2024
44e3b01
Add the restaurant dashboard page and implement the view count feature.
maomao0007 Jul 4, 2024
02398bf
Modify the categoryid of the restaurant in the seeder
maomao0007 Jul 4, 2024
4f54470
feat: add categories navbar on restaurants index page
maomao0007 Jul 4, 2024
d4d1ff1
feat: add pagination on restaurants index page
maomao0007 Jul 5, 2024
c033eed
feat: add comment model
maomao0007 Jul 5, 2024
58cf630
feat: add post comment on restaurant page
maomao0007 Jul 5, 2024
aa03b7a
feat: show comments on restaurant page
maomao0007 Jul 5, 2024
ca8cd23
feat: add delete comment for admin
maomao0007 Jul 5, 2024
88fc48c
Merge remote-tracking branch 'origin/R03-test' into R03
maomao0007 Jul 6, 2024
d9f04ff
Add a profile page for the user.
maomao0007 Jul 6, 2024
cdc1f22
Add the user profile along with the user's comment list.
maomao0007 Jul 7, 2024
fefdbfa
Merge commit 'a449027c7d98265ce88753f16b1e8b46d7c42c21'
maomao0007 Jul 7, 2024
36d4d31
Merge branch 'R03'
maomao0007 Jul 7, 2024
5307ab5
feat: add feeds page
maomao0007 Jul 8, 2024
b420708
eat: create favorite model
maomao0007 Jul 8, 2024
ccb3be3
feat: add favorite/unfavorite button at index page
maomao0007 Jul 8, 2024
2e8a0d0
feat: get user's favorited restaurants & switch button
maomao0007 Jul 10, 2024
580f69b
Merge remote-tracking branch 'origin/R04-test' into R04
maomao0007 Jul 10, 2024
b387053
feat: add like/unlike button at index page
maomao0007 Jul 11, 2024
145bf14
feat: get user's favorited restaurants & switch button
maomao0007 Jul 11, 2024
943a0ca
feat: get user's likd restaurants & switch button
maomao0007 Jul 11, 2024
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
13 changes: 13 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Node.js test

on:
<<<<<<< HEAD
pull_request_target:
branches:
- main
Expand All @@ -11,6 +12,14 @@ on:
# - '*-test'
# pull_request:
# branches:
=======
push:
branches:
# - main
- '*-test'
pull_request:
branches:
>>>>>>> origin/R01-test
# - main

env:
Expand Down Expand Up @@ -38,11 +47,15 @@ jobs:
# mysql user: 'github' # Required if "mysql root password" is empty, default is empty. The superuser for the specified database. Can use secrets, too
# mysql password: 'password' # Required if "mysql user" exists. The password for the "mysql user"
- run: mysql --version
<<<<<<< HEAD
- run: echo "checkout head ${{ github.event.pull_request.head.sha }}"
- run: echo "base ${{ github.event.pull_request.base.sha }}"
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
=======
- uses: actions/checkout@v3
>>>>>>> origin/R01-test
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
Expand Down
45 changes: 37 additions & 8 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,42 @@
const express = require('express')
const routes = require('./routes')
const path = require("path"); // 引入 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"); // 引入 handlebars-helpers
const { getUser } = require("./helpers/auth-helpers");
const routes = require("./routes");

const app = express()
const port = process.env.PORT || 3000
const app = express();
const port = process.env.PORT || 3000;
const SESSION_SECRET = "secret";
const db = require("./models"); // 暫時新增這行,引入資料庫,檢查完可刪
// 註冊 Handlebars 樣板引擎,並指定副檔名為 .hbs
app.engine("hbs", handlebars({ extname: ".hbs", helpers: handlebarsHelpers }));
// 設定使用 Handlebars 做為樣板引擎
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()); // 增加這行,初始化 Passport
app.use(passport.session()); // 增加這行,啟動 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"); // 設定 success_msg 訊息
res.locals.error_messages = req.flash("error_messages"); // 設定 warning_msg 訊息
res.locals.user = getUser(req);
next();
});

app.use(routes)
app.use(routes);

app.listen(port, () => {
console.info(`Example app listening on port ${port}!`)
})
console.info(`Example app listening on port ${port}!`);
});

module.exports = app
module.exports = app;
50 changes: 50 additions & 0 deletions config/passport.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const passport = require("passport");
const LocalStrategy = require("passport-local");
const bcrypt = require("bcryptjs");
const { User, Restaurant, Like } = require("../models");
// set up 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, {
include: [
{ model: Restaurant, as: "FavoritedRestaurants" },
{ model: Restaurant, as: "LikedRestaurants" }
]
})
.then((user) => cb(null, user.toJSON()))
.catch((err) => cb(err));
});
module.exports = passport;
132 changes: 132 additions & 0 deletions controllers/admin-controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
const { Restaurant, User, Category } = require("../models");
const { localFileHandler } = require("../helpers/file-helpers"); // 將 file-helper

const adminController = {
getRestaurants: (req, res, next) => {
return Restaurant.findAll({
raw: true,
nest: true,
include: [Category],
})
.then((restaurants) => res.render("admin/restaurants", { restaurants }))
.catch((err) => next(err));
},
createRestaurant: (req, res) => {
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; // 把檔案取出來
return localFileHandler(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) => {
return Restaurant.findByPk(req.params.id, {
//去資料庫用 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) => {
Promise.all([
Restaurant.findByPk(req.params.id, { raw: true }),
Category.findAll({ raw: true })
])

.then(([restaurant, categories]) => {
if (!restaurant) throw new Error("Restaurant didn'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;

return Promise.all([
Restaurant.findByPk(req.params.id),
localFileHandler(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) throw new Error("User didn't exist!")
if (user.email === '[email protected]') {
req.flash('error_messages', '禁止變更 root 權限')
return res.redirect('back')
}

return user.update({ isAdmin: !user.isAdmin })
})
.then(() => {
req.flash('success_messages', '使用者權限變更成功')
res.redirect('/admin/users')
})
.catch(err => next(err))
}
}

module.exports = adminController;
41 changes: 41 additions & 0 deletions controllers/category-controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
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) => {
Category.findByPk(req.params.id)
.then(category => {
if (!category) throw new error("Category doesn't exist!")
return category.destroy( )
})
.then(() => res.redirect("/admin/categories"))
.catch((err) => next(err));
}
}
module.exports = categoryController;
37 changes: 37 additions & 0 deletions controllers/comment-controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const { Comment, User, Restaurant } = require("../models");
const commentController = {
postComment: (req, res, next) => {
const { restaurantId, text } = req.body;
const userId = req.user.id;
if (!text) throw new Error("Comment text is required!");
return Promise.all([
User.findByPk(userId),
Restaurant.findByPk(restaurantId),
])
.then(([user, restaurant]) => {
if (!user) throw new Error("User didn't exist!");
if (!restaurant) throw new Error("Restaurant didn't exist!");
return Comment.create({
text,
restaurantId,
userId,
});
})
.then(() => {
res.redirect(`/restaurants/${restaurantId}`);
})
.catch((err) => next(err));
},
deleteComment: (req, res, next) => {
return Comment.findByPk(req.params.id)
.then((comment) => {
if (!comment) throw new Error("Comment didn't exist!");
return comment.destroy();
})
.then((deletedComment) =>
res.redirect(`/restaurants/${deletedComment.restaurantId}`)
)
.catch((err) => next(err));
},
};
module.exports = commentController;
Loading