Created
May 13, 2020 16:09
-
-
Save obrien-k/50bbde9197d0fd1297fa14e47788ed96 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Utility functions for rendering | |
*/ | |
// Based on the browser locale, provide a localized price | |
function formatLocalizedPrice (price) { | |
return new Intl.NumberFormat(navigator.language, {style: 'currency', currency: price.currencyCode}).format(price.value); | |
} | |
// Create a srcset string for responsive images | |
function renderSrcset(image) { | |
return `${image.img320px} 320w, ${image.img640px} 640w, ${image.img960px} 960w, ${image.img1280px} 1280w` | |
} | |
/* | |
Page rendering logic | |
*/ | |
function renderPage(data) { | |
// Set up the add-to-cart-url format | |
const addToCartURLFormat = `${data.site.settings.url.vanityUrl}/cart.php?action=add&product_id=` | |
// Render the HTML for the product listing by looping over each product in the response | |
document.getElementById('multi-desc').innerHTML = `${data.site.products.edges.map(node => renderProduct(node.product, addToCartURLFormat)).reduce((productsHtml, productHtml) => productsHtml += productHtml)}`; | |
} | |
function renderProduct(product, addToCartURLFormat) { | |
// Render the product into a bootstrap "card" | |
return ` | |
<div class="card" style="max-width: 33%;"> | |
${product.defaultImage ? `<img loading="lazy" class="card-img-top" style="min-height: 33%; object-fit: contain;" src="${product.defaultImage.img960px}" srcset="${renderSrcset(product.defaultImage)}" alt="${product.defaultImage.altText}">` : '' | |
} | |
<div class="card-body"> | |
<h5 class="card-title">${product.name} ${renderPrice(product.prices)}</h5> | |
<a href="${addToCartURLFormat}${product.entityId}" class="btn btn-primary">Add to cart</a> | |
</div> | |
</div>` | |
} | |
function renderPrice(prices) { | |
// Render the price component from the supplied prices | |
return `<span class="card-text text-muted">(${prices.retailPrice ? `<del><span class="font-italic">${formatLocalizedPrice(prices.price)}</span></del> ` : ''}${formatLocalizedPrice(prices.price)})</span>` | |
} | |
function getProductAndSiteInfo() { | |
return fetch('/graphql', { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
'Authorization': 'Bearer ' + token | |
}, | |
body: JSON.stringify({ | |
query: ` | |
query MyFirstQuery { | |
site { | |
products (entityIds: [`+arr+`]) { | |
edges { | |
product: node { | |
...ProductFields | |
} | |
} | |
} | |
settings { | |
storeName | |
url { | |
vanityUrl | |
} | |
} | |
} | |
} | |
fragment ProductFields on Product { | |
id | |
entityId | |
name | |
sku | |
path | |
defaultImage { | |
img320px: url(width: 320) | |
img640px: url(width: 640) | |
img960px: url(width: 960) | |
img1280px: url(width: 1280) | |
altText | |
} | |
prices { | |
price { | |
value | |
currencyCode | |
} | |
retailPrice { | |
value | |
currencyCode | |
} | |
} | |
} | |
`}), | |
}).then(res => res.json()) | |
.then(res => res.data); | |
} | |
getProductAndSiteInfo().then(data => { | |
// With our data loaded, render the product listing | |
renderPage(data); | |
}).catch(e => { | |
// Some error was encountered | |
throw(e); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment