This is my current code to check if a user needs to give a review or not (that works), but it seems a little janky
// This function checks if the user logging in with id has any reviews he needs to fill out
export async function requireUserReviews(id: string) {
let user = await db.user.findUnique({
where: {
id
},
include: {
teacherMeetings: true,
studentMeetings: true,
reviewsGiven: true
}
})
if (!user) {
throw new Error('User not found')
}
// An array of all the meetings you need a review for
let reviews: Meeting[] = []
const twoHrs = 1000 * 60 * 60 * 2
user.teacherMeetings.forEach((meeting) => {
if (
new Date(meeting.updatedAt) < new Date(Date.now() - twoHrs) &&
meeting.status !== 'cancelled'
) {
reviews.push(meeting)
}
})
user.studentMeetings.forEach((meeting) => {
if (
new Date(meeting.updatedAt) < new Date(Date.now() - twoHrs) &&
meeting.status !== 'cancelled'
) {
reviews.push(meeting)
}
})
// Filter out all the meetings for which you've already written a meeting for
reviews = reviews = reviews.filter((meeting) => {
if (!user) {
throw new Error('User not found in meeting filter')
}
let cond = true
// Does a linear search from each review given and sees if it's a review for a meeting review you want to give
user.reviewsGiven.every((review) => {
if (review.meetingId == meeting.id) {
cond = false
return false
}
return true
})
console.log(meeting.description, cond)
return cond
})
if (reviews.length > 0) {
console.log('reviews', reviews)
throw redirect(`/review/${reviews[0].id}`)
}
return user
}
Basically what it does is first grab the user from the id of the user. This user, I also grab a list of three relationships from this person (teacherMeetings, studentMeetings, and reviewsGiven). teacherMeetings is a list of all meetings this user has done where he was a teacher, studentMeetings is similar, and reviewsGiven is self-explanatory.
Then I go through each teacherMeeting and studentMeeting seeing if the meeting happened more than two hours ago and wasn’t cancelled. The reason I check if it happened two hours ago and not just now is because I don’t want to interrupt someone’s coding flow if they’re in the zone by forcing a review instantly, so I wait two hours.
If the meeting wasn’t cancelled and happened more than two hours ago, I push it to a reviews array. Afterwards, I filter the reviews array and check to see if I’ve already given a review for each review in the review arrays. I check if I’ve already given a review by checking each current element in review with a list of all reviews I’ve already given. If I’ve already given it, return false so filter filters it out. Keep the ones where I haven’t already given a review.
This is basically a o(n*m) sweep right here, n for # of reviews you should give and another m for # of reviews you’ve already given. Both n and m are equal if you’ve successfully given all the reviews you should. O(n^2) solution seems very janky, I was wondering if you had any better ideas?
In meeting, I have a relation for reviews[] but I can’t access meeting.reviews since reviews[] is a relation but taking advantage of this turns the o(n^2) mess into just o(1) since there’s only at most two reviews.
I could potentially also take the list of meetings and then for each meetingRequest do a database call and get the list of meetings, but then it becomes n database calls instead of just one, so even though it’s only o(n) * 2 (2 since each reviews only has at most 2 elements), it’s n database calls which may be costly.
What should I do?