# 🏅 Day 35 - 實作新增、取消特定貼文讚
練習整合運用先前提到的技巧、知識:
- router
- Mongoose findOneAndUpdate()
- req.params
- JWT middleware
實作出設計稿 `3-2.全體動態牆-有留言` 頁面的「新增、取消特定貼文讚」的功能
### 新增按讚
設計 POST `/posts/:id/likes` 路由,需登入才能請求(id 為貼文 ID)
* 當使用者登入並驗證 JWT 正確,修改資料庫中該貼文的 likes 欄位,將使用者 ID 加入 likes 陣列中(使用 [`$addToSet`](https://www.mongodb.com/docs/manual/reference/operator/update/addToSet/#-addtoset),避免加入重複的使用者 ID)
* 若新增成功,回傳成功訊息及修改的貼文 ID、新增的使用者 ID
### 移除按讚
設計 DELETE `/posts/:id/likes` 路由,需登入才能請求(id 為貼文 ID)
* 當使用者登入並驗證 JWT 正確,修改資料庫中該貼文的 likes 欄位,將使用者 ID 由 likes 陣列中移除(使用 [`$pull`](https://www.mongodb.com/docs/manual/reference/operator/update/pull/#-pull))
* 若移除成功,回傳成功訊息及修改的貼文 ID、已移除的使用者 ID
依照上方需求完整以下程式碼,補上 `...` 的部分
`app.js`
```javascript=
const postsRouter = require('./routes/posts');
app.use('/posts', postsRouter);
```
`routes/posts.js`
```javascript=
// routes/posts.js
const router = express.Router();
const Post = require('../models/postsModel');
const { isAuth } = require('../service/auth');
// 新增按讚
router....('...', ..., handleErrorAsync(async (req, res, next) => {
const _id = req.params....;
await Post....(
{ _id },
{ $addToSet: { likes: req.user.... } }
);
res.status(201).json({
status: 'success',
postId: ...,
userId: ...
});
}));
// 移除按讚
router....('...', ..., handleErrorAsync(async (req, res, next) => {
const _id = req.params....;
await Post....(
{ _id },
{ $pull: { likes: req.user.... } }
);
res.status(201).json({
status: 'success',
postId: ...,
userId: ...
});
}))
module.exports = router;
```
## 回報流程
將答案寫在 CodePen 並複製 CodePen 連結貼至底下回報就算完成了喔!
解答位置請參考下圖(需打開程式碼的部分觀看)

<!-- 解答:
`app.js`
```javascript=
const postsRouter = require('./routes/posts');
app.use('/posts', postsRouter);
```
`routes/posts.js`
```javascript=
// routes/posts.js
const router = express.Router();
const Post = require('../models/postsModel');
const { isAuth } = require('../service/auth');
// 新增按讚
router.post('/:id/likes', isAuth, handleErrorAsync(async (req, res, next) => {
const _id = req.params.id;
await Post.findOneAndUpdate(
{ _id },
{ $addToSet: { likes: req.user.id } }
);
res.status(201).json({
status: 'success',
postId: _id,
userId: req.user.id
});
}));
// 移除按讚
router.delete('/:id/likes', isAuth, handleErrorAsync(async (req, res, next) => {
const _id = req.params.id;
await Post.findOneAndUpdate(
{ _id },
{ $pull: { likes: req.user.id } }
);
res.status(201).json({
status: 'success',
postId: _id,
userId: req.user.id
});
}))
module.exports = router;
```
-->
回報區
---
<!--
將答案貼至下方表格內,格式:
| Discord 暱稱 | [CodePen](連結) |
-->
| Discord | CodePen / 答案 |
|:-------------:|:-----------------:|
| xxx | [CodePen]() |
| jenny7532 | [CodePen](https://codepen.io/wei-chen-wu/pen/gOJrEBB) |
| william威良 | [CodePen](https://codepen.io/snowman12320/pen/jOoqJQN) |
| Chia Pin | [CodePen](https://codepen.io/joker-cat/pen/oNRxRpg) |
| wei | [CodePen](https://hackmd.io/@xu7yoa5cSsqaron7h9XhUw/rJFX7WimR)|
|zaoannihao|[Codepen](https://codepen.io/ckhwdvrx-the-solid/pen/KKLMPMZ?editors=0010)|
|苡安|[hackmd](https://hackmd.io/@L7K9-66lSeagS28AP0_GjQ/BJX4-MnX0)|
| runweiting |[Codepen](https://codepen.io/weiting14/pen/LYobjvQ)|
| mei | [CodePen](https://codepen.io/l_umei/pen/yLWgmdL?editors=0010)|
| Fabio20 | [CodePen](https://codepen.io/fabio7621/pen/XWwMYKK?editors=0010) |
|Lobinda|[HackMD](https://hackmd.io/@Lobinda/ryxJLPY6VR)|
| Hank | [CodePen](https://codepen.io/tw1720/pen/KKLKqjx)|