Product Detail
Components
- Component to mange the view of the product detail
- File locate: theme/src/components/productDetails/index.js
Code Snippets
<div>
<section id="product-detail">
<div className="container">
<div className="gallery">
<Gallery images={product.images} />
</div>
<div className="product-info">
<h2>{product.name}</h2>
<Price product={product} variant={selectedVariant} isAllOptionsSelected={isAllOptionsSelected} settings={settings} />
<Options options={product.options} onChange={this.onOptionChange} />
<div className="btn-wrap">
<AddToCartButton product={product} variant={selectedVariant} addCartItem={this.addToCart} isAllOptionsSelected={isAllOptionsSelected} addingCartItem={addingCartItem}/>
<a className="add-favorite" onClick={this.likeProduct}><img alt="img" src={this.state.liked ? "/assets/images/cestore/ic_favorited.svg" : "/assets/images/cestore/ic_favorite.svg"}/><span>Add To Favorites</span></a>
</div>
</div>
</div>
</section>
<section id="product-content">
<div className="container">
<nav className="tab">
<ul>
<li><a className={this.state.showDescription ? "active" : ""} onClick={()=>this.setState({showDescription:true})}>Description</a></li>
<li><a className={!this.state.showDescription ? "active" : ""} onClick={()=>this.setState({showDescription:false})}>Details</a></li>
</ul>
</nav>
{this.state.showDescription && <Description description={product.description} />}
{!this.state.showDescription && <Attributes attributes={product.attributes} />}
</div>
</section>
<RelatedProducts
settings={settings}
addCartItem={this.addToCart}
ids={product.related_product_ids}
limit={10}
/>
{themeSettings.show_viewed_products &&
<ViewedProducts
settings={settings}
addCartItem={this.addToCart}
product={product}
limit={themeSettings.limit_viewed_products || 4}
/>
}
{themeSettings.disqus_shortname && themeSettings.disqus_shortname !== '' &&
<section id="comments">
<div className="container">
<Disqus
shortname={themeSettings.disqus_shortname}
identifier={product.id}
title={product.name}
url={product.url}
/>
</div>
</section>
}
<section id="subscribe">
<div className="container">
<h2>Subscribe and Get 15% Off</h2>
<form>
<input type="text" placeholder="Your email"/>
<a><img src="/assets/images/cestore/ic_send_mail.svg" alt="img"/></a>
</form>
</div>
</section>
</div>
Screenshots
Image Galleries
Components
- Mange the UI for the product detial galleries
- The thumnail position can be controlled from the admin site: http://localhost:3000/admin/products
- File locate: theme/src/components/productDetails/gallery.js
Code Snippets
<Fragment>
<ImageGallery
items={imagesArray}
showThumbnails={showThumbnails}
onClick={this.openLightbox}
lazyLoad={true}
slideInterval={2000}
showNav={themeSettings.product_gallery_shownav === true}
showBullets={showThumbnails}
showPlayButton={false}
showFullscreenButton={false}
slideOnThumbnailHover={true}
thumbnailPosition={themeSettings.product_thumbnail_position}
onSlide={this.setPhotoIndex}
/>
{lightboxIsOpen &&
<Lightbox
reactModalStyle={{ overlay: { zIndex: 1099 } }}
mainSrc={originalImages[lightboxPhotoIndex]}
nextSrc={originalImages[(lightboxPhotoIndex + 1) % originalImages.length]}
prevSrc={originalImages[(lightboxPhotoIndex + originalImages.length - 1) % originalImages.length]}
onCloseRequest={this.closeLightbox}
onMovePrevRequest={() => this.setState({
lightboxPhotoIndex: (lightboxPhotoIndex + originalImages.length - 1) % originalImages.length,
})}
onMoveNextRequest={() => this.setState({
lightboxPhotoIndex: (lightboxPhotoIndex + 1) % originalImages.length,
})}
/>
}
</Fragment>
Screenshots
Components
- In order to change the change the Disqus user, Go to Admin / Setting / Theme to change the DISQUS shortname
- File locate: theme/src/components/productDetails/index.js and theme/src/components/comments/disqus.js
Code Snippets
{themeSettings.disqus_shortname && themeSettings.disqus_shortname !== '' &&
<section id="comments">
<div className="container">
<Disqus
shortname={themeSettings.disqus_shortname}
identifier={product.id}
title={product.name}
url={product.url}
/>
</div>
</section>
}
import React from 'react'
const DISQUS_CONFIG = [
'shortname', 'identifier', 'title', 'url', 'category_id', 'onNewComment'
];
let __disqusAdded = false;
function copyProps(context, props, prefix = '') {
Object.keys(props).forEach((prop) => {
context[prefix + prop] = props[prop];
});
if (typeof props.onNewComment === 'function') {
context[prefix + 'config'] = function config() {
this.callbacks.onNewComment = [
function handleNewComment(comment) {
props.onNewComment(comment);
}
];
};
}
}
export default class Disqus extends React.PureComponent {
constructor(props) {
super(props);
}
componentDidMount() {
this.loadDisqus();
}
componentDidUpdate() {
this.loadDisqus();
}
addDisqusScript() {
if (__disqusAdded) {
return;
}
const child = this.disqus = document.createElement('script');
const parent = document.getElementsByTagName('head')[0] ||
document.getElementsByTagName('body')[0];
child.async = true;
child.type = 'text/javascript';
child.src = '//' + this.props.shortname + '.disqus.com/embed.js';
parent.appendChild(child);
__disqusAdded = true;
}
loadDisqus() {
const props = {};
// Extract Disqus props that were supplied to this component
DISQUS_CONFIG.forEach((prop) => {
if (!!this.props[prop]) {
props[prop] = this.props[prop];
}
});
// Always set URL
if (!props.url || !props.url.length) {
props.url = window.location.href;
}
// If Disqus has already been added, reset it
if (typeof DISQUS !== 'undefined') {
DISQUS.reset({
reload: true,
config: function config() {
copyProps(this.page, props);
// Disqus needs hashbang URL, see https://help.disqus.com/customer/portal/articles/472107
this.page.url = this.page.url.replace(/#/, '') + '#!newthread';
}
});
} else { // Otherwise add Disqus to the page
copyProps(window, props, 'disqus_');
this.addDisqusScript();
}
}
render() {
return <div id="disqus_thread" />;
}
}
Screenshots