Files
mediglobe/assets/js/product-renderer.js
T
2026-03-02 13:22:47 +05:30

301 lines
8.3 KiB
JavaScript

function renderRelatedProducts(product) {
const container = document.querySelector(".related-grid");
if (!container || !product.relatedProductIds) return;
const relatedProducts = product.relatedProductIds
.map((id) => PRODUCTS.find((p) => p.id === id))
.filter(Boolean);
container.innerHTML = relatedProducts
.map(
(p) => `
<div class="product-card">
<div class="product-img">
${
p.pricing.discountPercent
? `<div class="product-disc">-${p.pricing.discountPercent}%</div>`
: ""
}
<img
src="${p.media.mainImage}"
alt="${p.basic.name}"
width="200"
height="200"
loading="lazy"
decoding="async"
draggable="false" />
</div>
<div class="product-body">
<div class="product-name">${p.basic.name}</div>
<div class="product-rating">★★★★★</div>
<div class="product-price">
<span class="rp-now">₹${p.pricing.price}</span>
${
p.pricing.originalPrice
? `<span class="rp-old">₹${p.pricing.originalPrice}</span>`
: ""
}
</div>
<a href="product.html?id=${
p.id
}" target="_blank" class="product-add-btn">
View Product
</a>
</div>
</div>
`
)
.join("");
}
function renderProduct(productId) {
const product = PRODUCTS.find((p) => p.id === productId);
if (!product) {
console.error("Product not found:", productId);
return;
}
// =========================
// BASIC INFO
// =========================
const { basic, pricing, media, rating } = product;
// Title
document.title = product.seo?.title || basic.name;
document.querySelector(".product-title").textContent = basic.name;
// Breadcrumb
const breadcrumbCurrent = document.querySelector(".breadcrumb-bar .current");
if (breadcrumbCurrent)
breadcrumbCurrent.textContent = basic.shortName || basic.name;
// Image
const mainImg = document.querySelector(".gallery-main img");
if (mainImg && media?.mainImage) {
mainImg.src = media.mainImage;
mainImg.alt = basic.name;
}
// =========================
// PRICING
// =========================
document.querySelector(".price-current").textContent = `₹${pricing.price}`;
document.querySelector(".price-original").textContent = pricing.originalPrice
? `₹${pricing.originalPrice}`
: "";
document.querySelector(".price-badge").textContent = pricing.discountPercent
? `-${pricing.discountPercent}%`
: "";
// Stock
const stockStatus = document.querySelector(".stock-status");
if (stockStatus) {
stockStatus.innerHTML = `
<span class="stock-dot"></span>
${pricing.stockStatus} — Ships within ${pricing.shipsWithin}
`;
}
// =========================
// RATING
// =========================
if (rating) {
document.querySelector(".rating-count").textContent =
rating.average.toFixed(1);
document.querySelector(
".review-link"
).textContent = `${rating.totalReviews} Reviews`;
const soldText = document.querySelector(".rating-row span[style]");
if (soldText) soldText.textContent = `${rating.sold} sold`;
// Reviews tab count
const reviewTabBtn = document.querySelectorAll(".tab-nav-btn")[2];
if (reviewTabBtn)
reviewTabBtn.textContent = `Reviews (${rating.totalReviews})`;
// Big rating
const scoreEl = document.querySelector(".rating-big .score");
if (scoreEl) scoreEl.textContent = rating.average.toFixed(1);
const totalEl = document.querySelector(".rating-big .total");
if (totalEl)
totalEl.textContent = `Based on ${rating.totalReviews} reviews`;
// Rating bars
const bars = document.querySelectorAll(".rating-bar-row");
bars.forEach((bar) => {
const label = bar.querySelector(".bar-label").textContent.trim()[0];
const count = rating.breakdown[label] || 0;
const percent = rating.totalReviews
? (count / rating.totalReviews) * 100
: 0;
bar.querySelector(".bar-fill").style.width = `${percent}%`;
bar.querySelector(".bar-count").textContent = count;
});
}
// =========================
// SUMMARY
// =========================
document.querySelector(".product-short-desc").textContent =
product.summary.shortDescription;
// Benefit pills
const pillsContainer = document.querySelector(".benefit-pills");
if (pillsContainer) {
pillsContainer.innerHTML = product.summary.benefitPills
.map((p) => `<span class="benefit-pill">${p.icon} ${p.text}</span>`)
.join("");
}
// Meta
document.querySelector(".meta-row span:last-child").textContent = basic.sku;
document
.querySelectorAll(".meta-row")[1]
.querySelector("span:last-child").textContent = basic.weight;
document
.querySelectorAll(".meta-row")[2]
.querySelector("span:last-child").textContent = `₹${pricing.price}`;
// Categories
const categoryContainer = document
.querySelectorAll(".meta-row")[3]
.querySelector("div");
categoryContainer.innerHTML = basic.category
.map((c) => `<span class="meta-tag">${c}</span>`)
.join("");
// Tags
const tagContainer = document
.querySelectorAll(".meta-row")[4]
.querySelector("div");
tagContainer.innerHTML = basic.tags
.map((t) => `<span class="meta-tag">${t}</span>`)
.join("");
// Ideal for
document
.querySelectorAll(".meta-row")[5]
.querySelector("span:last-child").textContent = basic.idealFor;
// =========================
// DESCRIPTION TAB
// =========================
const descTab = product.descriptionTab;
document.querySelector(".desc-lead").textContent = descTab.lead;
const descBody = document.querySelector(".desc-body");
descBody.innerHTML = descTab.paragraphs.map((p) => `<p>${p}</p>`).join("");
// Features
const featuresContainer = document.querySelector(".desc-features");
featuresContainer.innerHTML = descTab.features
.map(
(f) => `
<div class="desc-feature">
<div class="feat-icon">${f.icon}</div>
<div class="feat-text">
<strong>${f.title}</strong>
<span>${f.text}</span>
</div>
</div>
`
)
.join("");
// How To Use
const howSteps = document.querySelector(".how-steps");
howSteps.innerHTML = descTab.howToUse
.map(
(step, i) => `
<div class="how-step">
<div class="step-num">${i + 1}</div>
${step}
</div>
`
)
.join("");
// =========================
// INGREDIENTS TAB
// =========================
const ingTab = product.ingredientsTab;
document
.querySelectorAll(".tab-pane")[1]
.querySelector(".desc-lead").textContent = ingTab.lead;
const ingGrid = document.querySelector(".ingredients-grid");
ingGrid.innerHTML = ingTab.ingredients
.map(
(i) => `
<div class="ingredient-card">
<div class="ing-icon">${i.icon}</div>
<div class="ing-name">${i.name}</div>
<div class="ing-role">${i.role}</div>
</div>
`
)
.join("");
document.querySelector(
".full-ingredients"
).innerHTML = `<strong>Full Ingredient List:</strong> ${ingTab.fullIngredients}`;
// =========================
// REVIEWS TAB
// =========================
const reviewList = document.querySelector(".review-list");
reviewList.innerHTML = product.reviews
.map(
(r) => `
<div class="review-card">
<div class="review-header">
<div class="reviewer-info">
<div class="reviewer-avatar">${r.avatarLetter}</div>
<div>
<div class="reviewer-name">${r.name}</div>
<div class="reviewer-date">${r.date}</div>
</div>
</div>
<div class="review-stars">${"★".repeat(r.rating)}${"☆".repeat(
5 - r.rating
)}</div>
</div>
<div class="review-title">${r.title}</div>
<div class="review-text">${r.text}</div>
${
r.verified
? `<div class="verified-badge">✓ Verified Purchase</div>`
: ""
}
</div>
`
)
.join("");
// =========================
// SHIPPING TAB
// =========================
const shippingTab = product.shipping;
const shippingLead = document
.querySelectorAll(".tab-pane")[3]
.querySelector(".desc-lead");
shippingLead.textContent = shippingTab.lead;
const shippingBody = document
.querySelectorAll(".tab-pane")[3]
.querySelector(".desc-body");
shippingBody.innerHTML = shippingTab.policies
.map((p) => `<p><strong>${p.title}:</strong> ${p.text}</p>`)
.join("");
renderRelatedProducts(product);
}