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.
COMMENTS:
Leave a comment: