# 🏅 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 連結貼至底下回報就算完成了喔! 解答位置請參考下圖(需打開程式碼的部分觀看) ![](https://i.imgur.com/vftL5i0.png) <!-- 解答: `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)|