workout.js 4.1 KB

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