Comments and rating for shop products with firebase (Part 2)

In the previous post I implemented a rating and commenting system for shop products. This was done on the individual product pages. Now I have written a little script to fetch and display the rating on products in the category view. To get the full functionality working, please also use the code from my previous post as it describes how the rating is created, which is necessary before it can be retrieved and displayed. I found out that the product ID, which is a unique identifier for each product in your shop, is listed in a data attribute. This eliminated the need to fetch anything from JSONs simplifying the operation. Good to know for future reference.

HTML:

JAVASCRIPT:

<!--SHOP PRODUCT RATING IN CATEGORY VIEW-->
<script type="module">
// Initialize Firebase
import { initializeApp } from 'https://www.gstatic.com/firebasejs/10.12.5/firebase-app.js';
import { getAuth } from 'https://www.gstatic.com/firebasejs/10.12.5/firebase-auth.js';
import { getFirestore, doc, setDoc, getDoc, collection, query, getDocs, limit, where } from 'https://www.gstatic.com/firebasejs/10.12.5/firebase-firestore.js';
const firebaseConfig = {
apiKey: "-----",
authDomain: "-----",
projectId: "----",
storageBucket: "------",
messagingSenderId: "------",
appId: "------",
measurementId: "---"
};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);
// Main
document.addEventListener('DOMContentLoaded', async function () {
const subString = 'shop';
const subStringTwo = 'shop/p/';
const getURL = window.location.href;
if (getURL.includes(subString) && !getURL.includes(subStringTwo)) {
const productItems = document.querySelectorAll('.grid-item');  
// Function to embed the rating stars beneath the product title
function embedRatingStars(productItem, averageRating) {
const roundedRating = Math.min(Math.max(0, Math.round(averageRating)), 5);
const filledStars = '★'.repeat(roundedRating);
const emptyStars = '☆'.repeat(5 - roundedRating);
const ratingStarsElement = document.createElement('div');
ratingStarsElement.className = 'rating-stars-category';
ratingStarsElement.innerHTML = `${filledStars}${emptyStars}`;
const productTitleElement = productItem.querySelector('.grid-title');
productTitleElement.insertAdjacentElement('beforeend', ratingStarsElement);
}
// Function to fetch the average rating from Firestore
async function fetchAverageRating(productId) {
try {
const commentsCollection = collection(db, 'comments', 'shopComments', productId);
const q = query(commentsCollection);
const querySnapshot = await getDocs(q);
if (querySnapshot.empty) {
return null;
}
let totalRating = 0;
let numberOfRatings = 0;
let averageRating = null;
querySnapshot.forEach((doc) => {
const data = doc.data();
if (data.rating > 0) {
const rating = Number(data.rating);
totalRating += rating;
numberOfRatings++;
	}
});
if (numberOfRatings > 0) {
averageRating = totalRating / numberOfRatings;
}
return averageRating;
} catch (error) {
console.error('Error fetching rating:', error);
return null;
	}
} 
//Get product ID 
function extractProductId(productItem) {
return productItem.getAttribute('data-item-id');
}
//add the rating
for (const productItem of productItems) {
const productId = extractProductId(productItem);
if (productId) {
const averageRating = await fetchAverageRating(productId);
if (averageRating !== null) {
embedRatingStars(productItem, averageRating);
			}
		}
	} 
}
});
</script>
CSS:

The CSS remains unchanged from part 1.

Previous
Previous

Instant wish list display in live shop

Next
Next

Comments and rating for shop products with firebase (Part 1)