I am creating a workout/exercise logger, where user's can add a log of their set of an exercise to their account. User's will also be able to see their history of workouts and exercises (with set data). I am using mongoDB to store this data, with GraphQL and mongoose to query and mutate the data. I have seperated workout and exercise into their own types, as a workout object will only hold exercises and the sets that were recorded in the last 4 hours (duration of workout), while the exercise object will hold all sets that were ever logged by the user.
Type Definitions
type Workout {
id: ID!
workoutName: String!
username: String!
createdAt: String
exercises: [Exercise]!
notes: String
}
type Exercise {
id: ID!
exerciseName: String!
username: String!
sets: [Set]!
}
type Set {
id: ID!
reps: Int!
weight: Float!
createdAt: String!
notes: String
}
My problem lies in my resolver code for adding a set (mutation). This resolver should:
- Query the database whether the exercise has ever been done by the user, by checking the name of the exercise with a match in the database, if there is a match, add the set data the user inputted to it, otherwise, create a new exercise entry first and then add the set to it.
- Query the database whether there is a workout that has been done in the last 4 hours. If there isn't a match, create a new workout entry in the database. If there is a workout, check for a matching exercise name on the workout object to add the set data to or create a new exercise entry for it.
I realise that this mutation will be fairly large and will combine both the querying and mutation of data together. So I'm wondering if I can call seperate queries/mutations from my addSet resolver similar to a function call? Or is there another method that I should be going about this?
addSet Resolver
async addSet(_, { exerciseName, reps, weight, notes }, context) {
const user = checkAuth(context); // Authenticates and gets logged in user's details
if (exerciseName.trim() === '') {
throw new UserInputError('Empty Field', {
// Attached payload of errors - can be used on client side
errors: {
body: 'Choose an exercise'
}
})
} else {
exerciseName = exerciseName.toLowerCase();
console.log(exerciseName);
}
if ((isNaN(reps) || reps === null) || (isNaN(weight) || reps === null)) {
throw new UserInputError('Empty Fields', {
// Attached payload of errors - can be used on client side
errors: {
reps: 'Enter the number of reps you did for this set',
weight: 'Enter the amount of weight you did for this set'
}
})
}
// TODO: Check to see if the exercise has been done before by the user. If it has, then update the entry by adding the set data to it. If not create a new entry for the
// exercise and then add the data to it - Completed and working.
const exerciseExists = await Exercise.findOne({ exerciseName: exerciseName, username: user.username });
if (exerciseExists) {
console.log("This exercise exists");
exerciseExists.sets.unshift({
reps,
weight,
username: user.username,
createdAt: Date.now(),
notes
})
await exerciseExists.save();
//return exerciseExists;
} else {
console.log("I don't exist");
const newExercise = new Exercise({
exerciseName,
user: user.id,
username: user.username,
});
const exercise = await newExercise.save();
console.log("new exercise entry");
exercise.sets.unshift({
reps,
weight,
username: user.username,
createdAt: Date.now(),
notes
})
await exercise.save();
//return exercise;
}
// TODO: Get the most recent workout from the user and check if the time it was done was from the last 4 hours. If it wasn't, create a new workout entry for the user.
// If it was within the ast 4 hours, check to see if the workout has an exercise that matches with one the user inputted. If there isn't an exercise, create a new entry
// and add the set data to it, otherwise update the existing entry for the exercise.
const workoutExists = await Workout.findOne({ username: username }).sort({ createdAt: -1 }); // Gets most recent workout by user
const now = Date.now();
if (now > workoutExists.createdAt + 14400000) { // Checks to see if the workout was less than 4 hours ago
console.log("workout was from another session");
// rest of code not implemented yet
} else {
console.log("workout is still in progress");
// rest of code not implemented yet
}
},