Initial commit
This commit is contained in:
@@ -0,0 +1,300 @@
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user