Average rating & % recommend in dynamic repeater

I would really appreciate it if anyone can help me with this.
I have a test website where I am testing the reviews for a supplier directory.
The website has no membership i.e. no one needs to log in to review.

The dynamic list is - Suppliers list
The dynamic page - is each supplier.

There are three collections.

  1. Suppliers - in this collection the supplier field key is title
  2. Reviews - in this collection the supplier field key is productId which is a reference field to Suppliers collection.
  3. review-stats - in this collection there are four columns as shown in the photo below.
    #rating
    #count
    #recommended
    These are all stored as numbers.

I have managed to follow the Wix example for adding reviews to the products and added that to the dynamic page. This is working fine.
No issues at all. This is the photo

I now want to add the average rating and the recommended % to the supplier list repeater.

Please see the photos:

  1. This is the repeater container showing the Rating display element

  1. This is the repeater container showing the % recommending text element

I thought that I would add the calculate the rating function to each item.

This is my code so far:

I am getting errors highlighted in orange and red.
And I think I have not completed the code.
(the comments after // are from the product page)

Please can anyone help me with this code?
so that the average rating and the percentage recommending also appear in each repeater container.

This is the link to the test website

https://pt-tips.wixsite.com/website/suppliers

p.s. I have gone through various posts on here but did not see a solution. Looked at so many youtube tutorials from Wix but nothing has jumped out.

I also emailed a Wix market expert, thinking it will not be a big job and was not expecting this response.
He said that the average ratings for the entire thing need to change… and wants to redo the collections/database…
and quoted me quite a bit to do it. This is my final desperate attempt to ask for help here, please.

Many thanks

Why is there no comprehensive examples or tutorials on this, as there are for other elements in Wix.

@_wix-2

Look at this link, a wix user does not have to go through all this to get it done… its not even done yet.

@hawaiiwedpedia
@andreas-kviby

Hi Chanel and Andreas, i noticed that in the old post you have helped others with this.
Please can you help me here? thank you

@yisrael-wix

I was finally able to get to the correct link from your profile.
I found the examples very helpful.

I have been looking for a solution to have the average rating on the repeater.
This one.
https://www.wix.com/gramps-workbench/ratings-by-user-vw

I will be grateful if you could do a similar example but instead of a lightbox, the recipe data is on a dynamic page.

Is this code adaptable to the dynamic page instead of a lightbox?

Thank you

Can you please add your current working (not working CODE) in a nicely formated CODE-BLOCK instead of showing your code on a pic?

You do not know what a CODE-BLOCK-features is?

Look here… ------> < / > find it in menu-options.

@russian-dima

Thank you for responding and helping.

Here are the details. I am including the working code so you can see how the rating is populated and calculated.

  1. Suppliers - in this collection the supplier field key is title
  2. Reviews - in this collection the supplier field key is productId which is a reference field to Suppliers collection.
  3. review-stats - in this collection there are four columns as shown in the photo below.
    #rating
    #count
    #recommended
    These are all stored as numbers.
    I have shown above how these collections look.

This is the code in the supplier profile page (similar to the product page)
This code is working

//-------------Imports-------------//

import wixData from 'wix-data';
import wixWindow from 'wix-window';

//-------------Global Variables-------------//

// Current product.
let product; 

//-------------Page Setup-------------//

$w.onReady(async function () {
    // Set the global product variable to the currently displayed product.
    product = await $w('#dynamicDataset').getCurrentItem(); 
    // Load the current product's reviews using the initReviews() function.
    initReviews(); 
});

// Loads the current product's reviews.
async function initReviews() {
    // Filter the "Reviews" dataset to contain only the reviews on the currently displayed product.
    await $w('#Reviews').setFilter(wixData.filter().eq('productId', product._id));
    // Show the reviews after the filter was set and applied on the dataset 
    showReviews();
    // Load the current product's statistics using the loadStatistics() function.
    loadStatistics();
}

// Load the current product's statistics.
async function loadStatistics() {
    // Get the statistics data based on the current product's ID.
    const stats = await wixData.get('review-stats', product._id); 
    // If statistics data for the product was found:
    if (stats) { 
        // Compute the product's average rating by dividing the total points by the number of ratings.
        let avgRating = (Math.round(stats.rating * 5 / stats.count) / 5); 
        // Compute the percentage of reviewers that recommend the product.
        let percentRecommended = Math.round(stats.recommended / stats.count * 100); 
        // Get the ratings element.
        let ratings = $w('#generalRatings');
        // Set the ratings element's average rating to the value calculated above. 
        ratings.rating = avgRating;
        // Set the ratings element's number of ratings to the count value from the statistics data.
        ratings.numRatings = stats.count;
        // Set the text for the recommended percentage element.
        $w('#recoPercent').text = `${percentRecommended} % would recommend`; 
        // Show the ratings element.
        $w('#generalRatings').show(); 
    // If there is no statistics data for the product:
    } else {
        // Set the text for the recommended percentage element to reflect the fact that there are no reviews.
        $w('#recoPercent').text = 'There are no reviews yet'; 
    }
    // Show the recommended percentage element only after it is populated to avoid flickering.
    $w('#recoPercent').show(); 
}

//-------------Repeater Setup -------------//

// Set up each item in the reivews repeater as it is loaded.
export function reviewsRepeater_itemReady($w, itemData, index) {
    // If the reviewer recommends the item:
    if (itemData.recommends) {
        // Set the "recommend text.
        $w('#recommendation').text = 'I recommend this supplier.';
    // If the reviewer does not recommend the item:
    } else {
        // Set the "don't recomend" text.
        $w('#recommendation').text = "I don't recommend this supplier.";
    }

    // If a photo was uploaded for the review:
    if (itemData.photo) { 
        // Set the image URL from the item data.
        $w('#reviewImage').src = itemData.photo;
        // Expand the image.
        $w('#reviewImage').expand();
    }

    // Set the ratings element's rating value.
    $w('#oneRating').rating = itemData.rating; 

    // Get the date that the review was entered.
    let date = itemData._createdDate; 
    // Format the date according to the date format settings on the user's computer.
    $w('#submissionTime').text = date.toLocaleString();
}

//-------------Data Setup -------------//

// Perform some setup when the dataset filter was completed.
export function showReviews() {
    // If at least one review has been submitted:
    if ($w('#Reviews').getTotalCount() > 0) {
        // Expand the strip that displays the reviews.
        $w('#reviewsStrip').expand();
    // If there are no reviews:
    } else {
        // Collapse the strip that displays the reviews.
        $w('#reviewsStrip').collapse(); //otherwise, hide it
    }
}

//-------------Event Handlers -------------//

// Set the action that occurs when a user clicks the "Write a Review" button.
export async function addReview_click(event, $w) {
    // Create an object containing the current product's ID to be sent to the review writing lightbox.
    const dataForLightbox = {
        productId: product._id
    };
    // Open the "Review Box" lightbox, send it the object created above, and wait for it to close.
    let result = await wixWindow.openLightbox('Review Box', dataForLightbox);
    // After the review lightbox is closed, refresh the reviews dataset so the new review appears on the page.
    $w('#Reviews').refresh();
    // Reload the current products statistics to reflect the new rating.
    setTimeout(() => {
        loadStatistics();
    }, 2000);
    // Show a thank you message.
    $w('#thankYouMessage').show();
}


This is the code in the lightbox that pops up when WRITE REVIEW is clicked.
This code is working but see two issues below

//-------------Imports-------------//

import wixWindow from 'wix-window';
import wixData from 'wix-data';

//-------------Global Variables-------------//

// Current product's ID. 
let productId;

//-------------Lightbox Setup-------------//

$w.onReady(function () {
    // Get the data passed by the page that opened the lightbox.
    productId = wixWindow.lightbox.getContext().productId;
    
    // Set the action that occurs before the review is saved.
    $w('#SubmitReviews').onBeforeSave(() => {
        // If no rating was set:
        if ($w('#radioRating').value === '') {
            // Display an error message.
            $w('#rateError').show();
            // Force the save to fail.
            return Promise.reject(); 
        }

        // If a rating was set, set the element values into the fields of the dataset item.
        // These values will be saved in the collection.
        $w('#SubmitReviews').setFieldValues({
            productId,
            rating: $w('#radioRating').value,
            recommends: $w('#radioGroup1').value
        });
    });
    
    // Set the action that occurs after the review is saved.
    $w('#SubmitReviews').onAfterSave(async () => {
        // Update the product's statistics using the updateStatistics() function.
        await updateStatistics($w('#radioGroup1').value);
        // When the statistics have been updated, close the lightbox to return the user to the product page.
        wixWindow.lightbox.close(); 
    });
});

// Update (or create) the product statistics.
async function updateStatistics(isRecommended) {
    // Get the review statistics for the current product from the "review-stats" collection.
    let stats = await wixData.get('review-stats', productId);

    // If statistics data already exist for this product:
    if (stats) {
        // Add the new rating to the total rating points.
        stats.rating += parseInt($w('#radioRating').value, 10); 
        // Increase the ratings count by 1.
        stats.count += 1; 
        // Increase the recommendations by one if the user recommends the product.
        stats.recommended += (isRecommended === "true") ? 1 : 0;
        // Update the new product statistics in the "review-stats" collection.  
        return wixData.update('review-stats', stats)
    }
    //If no statistics data exists for this product, create a new statistics item. 
    stats = {
        // Set the statistics item's ID to the current product's ID.
        _id: productId,
        // Set the statistics item's rating to the rating entered by the user.
        rating: parseInt($w('#radioRating').value, 10),
        // Set the statistics item's ratings count to 1 because this is the first rating.
        count: 1,
        // Set the statistics item's recommended property to 1 if the user recommends the product.
        recommended: (isRecommended === "true") ? 1 : 0
    };
    // Insert the new product statistics item into the "review-stats" collection.
    return wixData.insert('review-stats', stats)
}

//-------------Event Handlers-------------//

// Set the action that occurs when a rating is chosen.
export function radioRating_change(event, $w) {
    // Hide the error message.
    $w('#rateError').hide();
}


Lightbox code issues:
a) When closing the lightbox without submitting the review, the thank you message is displayed.
b) the lightbox lets review to be submitted without any radio buttons for stars to be selected. When this is done, the review does not appear on the reviews repeater.

Supplier list page (all items - dynamic)
CODES FOR THIS DON’T WORK
Now on the Supplier list page where the repeater is, I want to insert the average ratings in each container. This average rating is correctly calculated on the supplier profile page but when the data is populated in the
review-stats collection it does not populate the average rating.
So when I reference review-stats to Suppliers collection I don’t have option to select average rating.

The repeater in Suppliers list page is connected to suppliers collection.

The repeater is called supplerlist

There are two solutions I was thinking of to get average rating into the repeater.

  1. by amending the code in light box so it populates the average rating into the review-stats collection , OR

  2. by adding a function in the supplier list page so that it calculates the average rating from data in the review-stats and adds it to the repeater item container.

I have not been able to do No. 1 yet.

for no. 2, I tried the codes below.

Code A - but I know it’s not correct.

import wixData from 'wix-data';

$w.onReady(async function () {
    $w('#supplierlist').onItemReady(($item, itemData, index) => {
        $item('#generalRatings').text = itemData.region
        $item('#generalRatings2').text = itemData.recommended
    })
    const { items: suppliers } = await wixData.query('Suppliers').find()

    $w('#supplierlist').data = suppliers

});


Alternative to code A I tried code B:

import wixData from 'wix-data';

// define what is a product
let product;

$w.onReady(function () {
     $w('#supplierlist').data = product;

 // Load the current product's statistics.
     $w.onReady(async function loadstatistics() {
                            $w('#supplierlist').onItemReady(($item, itemData, index) => {

// Get the statistics data based on the current product's ID.
      const stats = await wixData.get('review-stats', product._id);
 // If statistics data for the product was found:
       if (stats) {
// Compute the product's average rating by dividing the total points by the number of ratings.
 let avgRating = (Math.round(stats.rating * 10 / stats.count) / 10);
 // Compute the percentage of reviewers that recommend the product.
 let percentRecommended = Math.round(stats.recommended / stats.count * 100);
// Get the ratings element.
   let ratings = $w('#generalRatings');
// Set the ratings element's average rating to the value calculated above. 
   ratings.rating = avgRating;
 // Set the ratings element's number of ratings to the count value from the statistics data.
  ratings.numRatings = stats.count;
  // Set the text for the recommended percentage element.
                                    $w('#recoPercent').text = `${percentRecommended} % would recommend`;
  // Show the ratings element.
                                    $w('#generalRatings').show();
  // If there is no statistics data for the product:
      } else {
 // Set the text for the recommended percentage element to reflect the fact that there are no reviews.
                                    $w('#recoPercent').text = 'There are no reviews yet';
      }
 // Show the recommended percentage element only after it is populated to avoid flickering.
                                $w('#recoPercent').show();
     })



//Alternative export function method

export function ReviewStatsDataset_ready() {

const stats = await wixData.get('review-stats', product._id);
let avgRating = (Math.round(stats.rating * 10 / stats.count) / 10);
let ratings = $w('#generalRatings');
                                $w('#supplierlist').forEachItem(($item, itemData, index) => {
    ratings.rating = avgRating;
    ratings.numRatings = stats.count;
     })
     }

So its the code on the Supplier list page that I am really stuck at.

If you can please help me figure out the right code to populate the supplier list page (item list page) with the average rating for each supplier from the supplier profile page, I will be eternally grateful.
Here is the link to the test website.
https://pt-tips.wixsite.com/website/suppliers

Thank you

I also found this code just very recently which I need to review and see if I can adapt it to my website situation. But I have a feeling I will struggle with this too :frowning:

This is from the recepies example by Brewmaster.

It has receipies in repeater with rating in each container and when clicking the container it opens into a lightbox rather then a dynamic item page.

Repeater page code:


import { getRecipe, rateRecipe, getRecipeRating, getUserRecipeRating } from 'backend/queries';
import wixWindow from 'wix-window';

let recipeId;
let recipeIdObj;
let changed = false;

$w.onReady(async function () {
    $w('#photo').hide(); // prevent placeholder picture from displaying
    recipeIdObj = wixWindow.lightbox.getContext();
    recipeId = recipeIdObj['recipeId'];

    let resp = await getRecipe(recipeId);
    let recipeItem = resp.items[0];
    $w('#photo').src = recipeItem.photo;
    $w('#photo').show(); // we have a picture so we can now display

    $w("#ingredients").html = recipeItem.ingredients;
    $w('#preparation').html = recipeItem.instructions;
    $w('#title').text = recipeItem.title;
    $w('#personal').text = recipeItem.personalTake;
    if (recipeItem.numRatings > 0) {
        $w('#ratingsDisplay').rating = recipeItem.rating;
        $w('#ratingsDisplay').numRatings = recipeItem.numRatings;
    } else {
        $w('#ratingsDisplay').rating = null; // ignore run-time error for this - needs null to clear rating
        $w('#ratingsDisplay').numRatings = 0;
    }

    let userRating = await getUserRecipeRating(recipeId);
    if (userRating > 0) {
        $w('#ratingsInput1').value = userRating;
    }
});

export async function ratingsInput1_change(event) {
    changed = true; // rating has been changed so tell page to refresh repeater

    $w('#ratingsInput1').disable();

    // get the new rating from the ratings input
    const newRating = $w('#ratingsInput1').value;
    await rateRecipe(recipeId, newRating);

    let recipeRating = await getRecipeRating(recipeId); 
    $w('#ratingsInput1').enable();
    
    if (recipeRating.count > 0) {
        $w('#ratingsDisplay').rating = recipeRating.ratingAvg;
        $w('#ratingsDisplay').numRatings = recipeRating.count;
    } else {
        $w('#ratingsDisplay').rating = null; // ignore run-time error for this - needs null to clear rating
        $w('#ratingsDisplay').numRatings = 0;
    }
}

export function close_click(event) {
    wixWindow.lightbox.close({
        "changed": changed
    });
}

light box code:

import { getRecipe, rateRecipe, getRecipeRating, getUserRecipeRating } from 'backend/queries';
import wixWindow from 'wix-window';

let recipeId;
let recipeIdObj;
let changed = false;

$w.onReady(async function () {
    $w('#photo').hide(); // prevent placeholder picture from displaying
    recipeIdObj = wixWindow.lightbox.getContext();
    recipeId = recipeIdObj['recipeId'];

    let resp = await getRecipe(recipeId);
    let recipeItem = resp.items[0];
    $w('#photo').src = recipeItem.photo;
    $w('#photo').show(); // we have a picture so we can now display

    $w("#ingredients").html = recipeItem.ingredients;
    $w('#preparation').html = recipeItem.instructions;
    $w('#title').text = recipeItem.title;
    $w('#personal').text = recipeItem.personalTake;
    if (recipeItem.numRatings > 0) {
        $w('#ratingsDisplay').rating = recipeItem.rating;
        $w('#ratingsDisplay').numRatings = recipeItem.numRatings;
    } else {
        $w('#ratingsDisplay').rating = null; // ignore run-time error for this - needs null to clear rating
        $w('#ratingsDisplay').numRatings = 0;
    }

    let userRating = await getUserRecipeRating(recipeId);
    if (userRating > 0) {
        $w('#ratingsInput1').value = userRating;
    }
});

export async function ratingsInput1_change(event) {
    changed = true; // rating has been changed so tell page to refresh repeater

    $w('#ratingsInput1').disable();

    // get the new rating from the ratings input
    const newRating = $w('#ratingsInput1').value;
    await rateRecipe(recipeId, newRating);

    let recipeRating = await getRecipeRating(recipeId); 
    $w('#ratingsInput1').enable();
    
    if (recipeRating.count > 0) {
        $w('#ratingsDisplay').rating = recipeRating.ratingAvg;
        $w('#ratingsDisplay').numRatings = recipeRating.count;
    } else {
        $w('#ratingsDisplay').rating = null; // ignore run-time error for this - needs null to clear rating
        $w('#ratingsDisplay').numRatings = 0;
    }
}

export function close_click(event) {
    wixWindow.lightbox.close({
        "changed": changed
    });
}


masterpage.js code


   // For full API documentation, including code examples, visit http://wix.to/94BuAAs

import wixUsers from 'wix-users';
import wixLocation from 'wix-location';

$w.onReady(function () {
    // Display the test buttons based on the user's
    // status - visitor, registered, paid
    if (wixUsers.currentUser.loggedIn) {
        console.log(wixUsers.currentUser.id);
        $w('#btnSignIn').label = "SIGN OUT";
        $w('#btnSignIn').show();
    }
    else {
        $w('#btnSignIn').label = "SIGN IN";
    }
});

wixUsers.onLogin( (user) => {
    $w('#btnSignIn').label = "SIGN OUT";
} );        

export async function btnLogOut_click(event, $w) {
    if (wixUsers.currentUser.loggedIn) {
        wixUsers.logout();
        $w('#btnLogOut').label = "SIGN IN";
        //wixLocation.to('/home');
    }
    else {
        wixUsers.promptLogin()
        .then( (user) => {
            $w('#btnLogOut').label = "SIGN OUT";
        } )
        .catch( (err) => {
            let errorMsg = err;          // "The user closed the login dialog"
        } );
    }
}

Backend code:


// Filename: backend/queries.jsw (web modules need to have a .jsw extension)

import wixData from 'wix-data';
import wixUsers from 'wix-users-backend';

// we're the site admin, so ignore the database permissions
const options = {
  "suppressAuth": true,
  "suppressHooks": true
};

export function getRecipes() {
    let query = wixData.query("Recipes");
    return query.find();
}

export async function _getRecipes() {
    let results = await wixData.query("Recipes").find();
    let items = results.items;
    let recipes = [];
    let recipe = {};
    items.forEach(async function (item) {
        let rating = await getRecipeRating(item._id);
        if (rating.count > 0) {
            recipe = { "_id": item._id, "title": item.title, "photo": item.photo, "ratingCount": rating.count, "ratingAvg": rating.ratingAvg };
        } else {
            recipe = { "_id": item._id, "title": item.title, "photo": item.photo };
        }
        recipes.push(recipe);
    });
    return recipes;
}

export function getRecipe(id) {
    let query = wixData.query("Recipes");
    query = query.eq("_id", id);
    return query.find();
}

export function getSearch(field, term) {
    let query = wixData.query("Recipes");
    if (term.length > 0) {
        query = query.contains(field, term);
    }
    return query.find();
}

export async function rateRecipe(recipeId, rating) {
    let userId = wixUsers.currentUser.id;
    let resp = await wixData.query("RecipeRatings")
        .eq('recipeId', recipeId)
        .eq('userId', userId)
        .find();
    let items = resp.items;
    let ratingItem = items[0];
    if (ratingItem === undefined || ratingItem === null) {
        ratingItem = {
            'recipeId': recipeId,
            'userId': userId,
            'rating': rating
        }
    } else {
        ratingItem.rating = rating;
    }
    await wixData.save("RecipeRatings", ratingItem, options);

    // update the recipe with the new ratings information
    let newRating = await getRecipeRating(recipeId);
    let recipe = await wixData.get('Recipes', recipeId);
    recipe.rating = newRating.ratingAvg;
    recipe.numRatings = newRating.count;
    await wixData.save("Recipes", recipe, options);
}

export async function getRecipeRating(recipeId) {

    console.log('getRecipeRating recipeId', recipeId);

    let filter = wixData.filter().eq("recipeId", recipeId);
    let resp = await wixData.aggregate("RecipeRatings")
        .filter(filter)
        .group("recipeId")
        .avg("rating")
        .count()
        .run();

    if (resp === undefined || resp.items.length === 0) {
        return { 'count': 0 };
    }

    let items = resp.items;
    let item = items[0];
    return item;
}

export async function getUserRecipeRating(recipeId) {
    let userId = wixUsers.currentUser.id;

    let results = await wixData.query("RecipeRatings")
        .eq("recipeId", recipeId)
        .eq("userId", userId)
        .find();
    let items = results.items;
    if (items.length === 0) {
        return 0;
    }
    let item = items[0];
    let rating = item.rating;
    return rating;
}


@russian-dima i hope you got my message below.
Please let me know if you need more info.

Thank you

I will take a look onto your issue on WEEKEND.
Your issue need more time for invastigations, or even for a reconstruction, for testing.

Thank you @russian-dima

You are putting to much informations onto your issue.
Normaly i always ask for more INPUT, but in your case, you put to much INPUT.

Try to be more precise to point out your exact code-issue.

So far as i can see, you connected your SUBMIT-BUTTON trough the PROPERTY-PANEL and i also can see that you are mixing DATASET + Wix-Data, what is causing in 90% of use-cases —> Problems, like you have them now.

But let’s try to solve them…
Since i don’t have the time to reconstruct your whole issued project, i will just put some console-logs onto my example-codes and make some little changes…

Your ISSUES starting on LIGHTBOX-PAGE, right?

PROBLEM-1:

When closing the lightbox without submitting the review, the thank you message is displayed.

I assume your SUBMISSION-BUTTON is on your —> LIGHTBOX, but this mentioned Submission-Button is → NOT ← coded, instead the Submission-Button will be connected through the PROPERTY-PANEL to do the SUBMISSION-FUNCTION, right?

So here our first problems begins. But this problem should be able to be resolved, how ?

When we take a look onto the given possibilities, we will find…

$w("#myDataset").onBeforeSave( () => {
  console.log("Continuing save");
  return true;
} );

…and…

$w("#myDataset").onBeforeSave( () => {
  console.log("Canceling save");
  return false;
} );

VELO-API-DOCS-QUOTE…

The onBeforeSave() function allows you to optionally perform actions right before a save() operation. When you call save(), the callback is run before the save operation. Any validity checks on the data are run after the callback runs. If the callback function returns false, returns a rejected Promise, or throws an error, the save operation is canceled.

Try the following one to get it to work…

light box code:

$w.onReady(function() {console.log("OnReady running...");
    productId = wixWindow.lightbox.getContext().productId;
    console.log("Product-ID: ", productId);

    let ratingValue = $w('#radioRating').value; console.log("Rating-Value: ", ratingValue);
    let recommends = $w('#radioGroup1').value;

    //ACTIONS BEFORE SAVE DATA.....
    $w('#SubmitReviews').onBeforeSave(()=> {console.log("BEFORE-SAVE running...");
        if(ratingValue) {console.log("Continuing save"); 
            $w('#SubmitReviews').setFieldValues({
                productId,
                rating: ratingValue,
                recommends: recommends
            });
            $w('#rateError').hide(); 
            return true;
        }
        else {console.log("Canceling save");
            $w('#rateError').show(); 
            return false;
            //return Promise.reject(); 
        }
    });


    //ACTIONS AFTER SAVE DATA.....
    $w('#SubmitReviews').onAfterSave(()=> {
        console.log("AFTER-SAVE running...");
        console.log("Data saved!");
        updateStatistics($w('#radioGroup1').value).then(()=>{
            console.log("Statistics have been updated!");
            wixWindow.lightbox.close();
        });     
    });
});

PROBLEM-2:

the lightbox lets review to be submitted without any radio buttons for stars to be selected. When this is done, the review does not appear on the reviews repeater.

Not completely understood → Do you have a pic?

You should use more CONSOLE-LOGS → this will help you to understand your own CODE much better during actions.

@russian-dima
Thank you for looking at the issue.

The radio button circled in red… one can submit a review without selecting any of the radio buttons. When this type of submission happens, the reviews repeater does not reflect the review data and the stars are all grey (not green)… the recommendation appears. Please see two photos below

PROBLEM-2:

the lightbox lets review to be submitted without any radio buttons for stars to be selected. When this is done, the review does not appear on the reviews repeater.

@russian-dima
I am sorry that I provided TOO MUCH info… I thought it would help.

You have identified 2 of the 3 problems.

I have just sent you the video of problem No.2 , I don’t know if that would mean that you will need to update the lightbox code that you have sent me to solve problem No.1.

The third problem is how to calculate the average ratings and the % that will recommend from the data in the rating-stats so that its populated in the repeater in the suppliers directory page.

This is the repeater on the supplier directory page

Thank you for helping.

Regarding problem 3, I have this code to calculate average rating and percentage recommended, but I don’t know how to correctly do it so that it populates the repeater.


import wixData from 'wix-data';


$w("#dynamicDataset").onReady( () => {
  $w("#supplierlist").onItemReady( ($item, itemData, index) => {

  
async function loadStatistics() { 

const stats = await wixData.get('review-stats', product._id); 

if (stats) { 
   let avgRating = (Math.round(stats.rating * 10 / 
   stats.count) / 10); 
   let percentRecommended = 
   Math.round(stats.recommended / stats.count * 100); 
   let ratings = $w('#generalRatings');         
   ratings.rating = avgRating;         
   ratings.numRatings = stats.count; 
   
  $w('#recoPercent').text = `${percentRecommended} % 
  would recommend`;         
  $w('#generalRatings').show();     } 
   
   else {         
   $w('#recoPercent').text = 'There are no reviews 
   yet';     
   }     
   $w('#recoPercent').show(); 
   }