workout.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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. Workout.deleteOne({_id: workout._id});
  40. Session.deleteMany({workout: workout._id});
  41. res.json({success: true});
  42. }catch(e){next(e)}
  43. }
  44. /*
  45. Create a new Workout object
  46. @param {Object} - Body data from the request
  47. @param {ObjectId} userId - ID of the user creating the workout
  48. @return {Workout} - Workout object
  49. */
  50. const createWorkout = (data, userId)=>{
  51. return new Workout({
  52. user: userId,
  53. name: data.name,
  54. exercises: data.exercises
  55. });
  56. }
  57. /*
  58. Throw error if user does not own workout
  59. @param {Workout} workout - Workout object
  60. @param {User} user - User object
  61. */
  62. const confirmOwnership = (workout, user)=>{
  63. if(workout.user.toString() !== user._id.toString()){
  64. throw new HttpError(403, "Unauthorized");
  65. }
  66. }
  67. /*
  68. Retrieve a single exercise from a workout
  69. @param {Workout} workout - Workout object
  70. @param {String} exerciseId - ID of the exercise to retrieve
  71. @return {Object} - Exercise object
  72. */
  73. const findExercise = (workout, exerciseId)=>{
  74. for(let i = 0; i < workout.exercises.length; i++){
  75. if(workout.exercises[i]._id.toString() === exerciseId){
  76. return workout.exercises[i];
  77. }
  78. }
  79. return null;
  80. }
  81. /*
  82. Update the order of exercises
  83. @param {Workout} workout - Workout object
  84. @param {Object} data - Request data containing exercise information
  85. @return {[Object]} - Array of updated exercises
  86. */
  87. const updateExercises = (exercises, data)=>{
  88. const newExercises = [];
  89. const existingIndices = [];
  90. for(let i = 0; i < data.existingExercises.length; i++){
  91. if(data.existingExercises[i].id){
  92. const j = exercises.findIndex(e => e._id.toString() === data.existingExercises[i].id);
  93. newExercises.push(exercises[j]);
  94. existingIndices.push(j);
  95. }else if(data.existingExercises[i].new){
  96. newExercises.push({
  97. name: data.existingExercises[i].new,
  98. notes: "",
  99. type: data.existingExercises[i].type,
  100. archived: false
  101. });
  102. }
  103. }
  104. for(let i = 0; i < exercises.length; i++){
  105. if(existingIndices.includes(i)) continue;
  106. exercises[i].archived = true;
  107. newExercises.push(exercises[i]);
  108. }
  109. return newExercises;
  110. }
  111. /*
  112. Create a new workout object for sending to the frontend
  113. @param {Workout} workout - Workout object
  114. @return {Object} - Modified Workout object
  115. */
  116. const responseWorkout = (workout)=>{
  117. return {
  118. id: workout._id,
  119. name: workout.name,
  120. exercises: workout.exercises
  121. };
  122. }
  123. export {
  124. createRoute,
  125. getRoute,
  126. addNoteRoute,
  127. updateWorkoutRoute,
  128. deleteRoute
  129. }