workout.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import Workout from "../models/Workout.js";
  2. import {HttpError} from "../HttpError.js";
  3. const createRoute = async (req, res, next)=>{
  4. try{
  5. const workout = createWorkout(req.body, res.locals.user._id);
  6. await workout.save();
  7. res.json(responseWorkout(workout));
  8. }catch(e){next(e)}
  9. }
  10. const getRoute = async (req, res, next)=>{
  11. try{
  12. const workouts = await Workout.find({user: res.locals.user._id});
  13. res.json(workouts.map(w => responseWorkout(w)));
  14. }catch(e){next(e)}
  15. }
  16. const addNoteRoute = async (req, res, next)=>{
  17. try{
  18. const workout = await Workout.findOne({_id: req.params.workoutId});
  19. confirmOwnership(workout, res.locals.user);
  20. const exercise = findExercise(workout.exercises, req.body.exercise);
  21. exercise.notes = req.body.note;
  22. await workout.save();
  23. res.json(responseWorkout(workout));
  24. }catch(e){next(e)}
  25. }
  26. const updateWorkoutRoute = async (req, res, next)=>{
  27. try{
  28. const workout = await Workout.findOne({_id: req.params.workoutId});
  29. workout.exercises = updateExercises(workout.exercises, req.body);
  30. await workout.save();
  31. res.json(responseWorkout(workout));
  32. }catch(e){next(e)}
  33. }
  34. const deleteRoute = async (req, res, next)=>{
  35. try{
  36. const workout = await Workout.findOne({_id: req.params.workoutId});
  37. confirmOwnership(workout, res.locals.user);
  38. Workout.deleteOne({_id: workout._id});
  39. res.json({success: true});
  40. }catch(e){next(e)}
  41. }
  42. /*
  43. Create a new Workout object
  44. @param {Object} - Body data from the request
  45. @param {ObjectId} userId - ID of the user creating the workout
  46. @return {Workout} - Workout object
  47. */
  48. const createWorkout = (data, userId)=>{
  49. return new Workout({
  50. user: userId,
  51. name: data.name,
  52. exercises: data.exercises
  53. });
  54. }
  55. /*
  56. Throw error if user does not own workout
  57. @param {Workout} workout - Workout object
  58. @param {User} user - User object
  59. */
  60. const confirmOwnership = (workout, user)=>{
  61. if(workout.user.toString() !== user._id.toString()){
  62. throw new HttpError(403, "Unauthorized");
  63. }
  64. }
  65. /*
  66. Retrieve a single exercise from a workout
  67. @param {Workout} workout - Workout object
  68. @param {String} exerciseId - ID of the exercise to retrieve
  69. @return {Object} - Exercise object
  70. */
  71. const findExercise = (workout, exerciseId)=>{
  72. for(let i = 0; i < workout.exercises.length; i++){
  73. if(workout.exercises[i]._id.toString() === exerciseId){
  74. return workout.exercises[i];
  75. }
  76. }
  77. return null;
  78. }
  79. /*
  80. Update the order of exercises
  81. @param {Workout} workout - Workout object
  82. @param {Object} data - Request data containing exercise information
  83. @return {[Object]} - Array of updated exercises
  84. */
  85. const updateExercises = (exercises, data)=>{
  86. const newExercises = [];
  87. const existingIndices = [];
  88. for(let i = 0; i < data.existingExercises.length; i++){
  89. if(data.existingExercises[i].id){
  90. const j = exercises.findIndex(e => e._id.toString() === data.existingExercises[i].id);
  91. newExercises.push(exercises[j]);
  92. existingIndices.push(j);
  93. }else if(data.existingExercises[i].new){
  94. newExercises.push({
  95. name: data.existingExercises[i].new,
  96. notes: "",
  97. type: data.existingExercises[i].type,
  98. archived: false
  99. });
  100. }
  101. }
  102. for(let i = 0; i < exercises.length; i++){
  103. if(existingIndices.includes(i)) continue;
  104. exercises[i].archived = true;
  105. newExercises.push(exercises[i]);
  106. }
  107. return newExercises;
  108. }
  109. /*
  110. Create a new workout object for sending to the frontend
  111. @param {Workout} workout - Workout object
  112. @return {Object} - Modified Workout object
  113. */
  114. const responseWorkout = (workout)=>{
  115. return {
  116. id: workout._id,
  117. name: workout.name,
  118. exercises: workout.exercises
  119. };
  120. }
  121. export {
  122. createRoute,
  123. getRoute,
  124. addNoteRoute,
  125. updateWorkoutRoute,
  126. deleteRoute
  127. }