How come the condition is not working?

I am given the products variable and need to create a function called rateProduct which rates the product, but if you've already rated that product you don't get to rate again. Now my code seems to be working however when I add my username the second time, I can still rate the same product again and again but the hardcoded userIds (fg12cy and zwf8md) would not be able to rate the same product again and again. When I console log the variable product, I see my personal username is added the first time into product, so why is it not following the condition coded like the hardcoded userIds?

const products = [
  {
    _id: 'eedfcf',
    name: 'mobile phone',
    description: 'Huawei Honor',
    price: 200,
    ratings: [
      { userId: 'fg12cy', rate: 5 },
      { userId: 'zwf8md', rate: 4.5 }
    ],
    likes: []
  },
  {
    _id: 'aegfal',
    name: 'Laptop',
    description: 'MacPro: System Darwin',
    price: 2500,
    ratings: [],
    likes: ['fg12cy']
  },
  {
    _id: 'hedfcg',
    name: 'TV',
    description: 'Smart TV:Procaster',
    price: 400,
    ratings: [{ userId: 'fg12cy', rate: 5 }],
    likes: ['fg12cy']
  }
  ]

function rateProduct (description, userId, rate){
    let correctDescription = true
    let ratingObject = {}
    ratingObject.userId = userId
    ratingObject.rate = rate
    let alert = true
    products.forEach((item) => {
      if(description === item.description){
        correctDescription = true;
        for(let i=0; i<item.ratings.length; i++){
          if(userId !== item.ratings[i].userId){
            alert = false
            item.ratings.push(ratingObject)
            return 
          } 
        } 
      } else{
        correctDescription = false
      } 
    })
    if(!correctDescription){
      return "No product is found to be rated"
    } else if(alert) {
      return "You've already rated this product"
    }
    return products
}
console.log(rateProduct("Smart TV:Procaster", "fg12cy", 4))
console.log(rateProduct("Smart TV:Procaster", "kris", 4)) /* initially updated product with "kris" and 4, but after calling the function again with "kris" and 3, the product here also got updated with "kris" and 3 - not staying as "kris" 
and 4 here for ratings inside product*/
console.log(rateProduct("Smart TV:Procaster", "kris", 3)) 
console.log(rateProduct("Smart TV:Procaster", "zwf8md", 2))

Comments (1)

Joe Clark's photo

Hope you figured it out by now, but if not...

        for(let i=0; i<item.ratings.length; i++){
          if(userId !== item.ratings[i].userId){
            alert = false
            item.ratings.push(ratingObject)
            return 
          } 
        }

It's adding the rating if the userId doesn't match, but if it does, it will simply return. The issue is that there's already a userId in the ratings array, before you get to "kris" (userId "fg12cy"). So, it will add it every time because it sees it exists every time. You need to change this loop to look for the user, and track if it's found or not, and only if it's not found after getting out of the loop should you add it to the ratings array.

By the way, "alert" is a javascript function, so I would avoid using that as a variable name, unless you intend to override the javascript function. Also, the "return" in the for loop will return from the fat arrow function. Not sure if that's what you intended, or if you just wanted to exit the for loop early but stay in the fat arrow function. To exit a for loop early, use "break".

Here's code with a couple of adjustments:

function rateProduct (description, userId, rate){
    let correctDescription = true
    let ratingObject = {}
    ratingObject.userId = userId
    ratingObject.rate = rate
    let found = false
    products.forEach((item) => {
      if(description === item.description){
        correctDescription = true;
        for(let i=0; i<item.ratings.length; i++){
          if(userId === item.ratings[i].userId){
            found = true
            break 
          } 
        }

        if (!found) {
           item.ratings.push(ratingObject)
        }
      } else{
        correctDescription = false
      } 
    })
    if(!correctDescription){
      return "No product is found to be rated"
    } else if(found) {
      return "You've already rated this product"
    }
    return products
}

Hope this helps.