Skip to content

Commit

Permalink
Merge pull request #152 from vtex-apps/bugfix/proptypes
Browse files Browse the repository at this point in the history
 Refact the ProductPrice component and fix console warnings
  • Loading branch information
Bruno Dias authored Aug 30, 2018
2 parents 423cff7 + b8db5da commit 7992154
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 123 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Changed
- Refact the `ProductPrice` component
### Fixed
- Update the propTypes of the components: `BuyButton`, `ProductPrice`, `ProductName`

## [2.0.0] - 2018-08-30
### Removed
- `QuantitySelector` that should not exist because the styleguide has a component with the same purpose, the `NumericStepper`.

## [2.0.0] - 2018-08-30
### Removed
Expand Down
4 changes: 2 additions & 2 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@
"dependencies": {
"vtex.store": "1.x",
"vtex.store-graphql": "2.x",
"vtex.styleguide": "5.x"
"vtex.styleguide": "6.x"
}
}
}
10 changes: 5 additions & 5 deletions react/components/BuyButton/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ export class BuyButton extends Component {
{this.props.children}
</Button>
) : (
<Button primary size="small" onClick={() => this.handleAddToCart()}>
{this.props.children}
</Button>
)}
<Button primary size="small" onClick={() => this.handleAddToCart()}>
{this.props.children}
</Button>
)}
</Fragment>
)
}
Expand All @@ -120,7 +120,7 @@ BuyButton.propTypes = {
/** Which seller is being referenced by the button */
seller: PropTypes.number.isRequired,
})
).isRequired,
),
/** Context used to call the add to cart mutation and retrieve the orderFormId **/
orderFormContext: contextPropTypes,
/** Component children that will be displayed inside of the button **/
Expand Down
2 changes: 1 addition & 1 deletion react/components/ProductName/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import ContentLoader from 'react-content-loader'
class ProductName extends Component {
static propTypes = {
/** Name of the product */
name: PropTypes.string.isRequired,
name: PropTypes.string,
/** Selected SKU name */
skuName: PropTypes.string,
/** Show sku */
Expand Down
97 changes: 97 additions & 0 deletions react/components/ProductPrice/Installments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React, { Component } from 'react'
import { isEmpty } from 'ramda'
import { FormattedMessage } from 'react-intl'
import PropTypes from 'prop-types'

import PricePropTypes from './propTypes'

/** Installments component */
export default class Installments extends Component {
render() {
const {
installments,
showLabels,
formatNumber,
currencyOptions,
} = this.props

if (!installments || isEmpty(installments)) {
return null
}

const noInterestRateInstallments = installments.filter(
installment => !installment.InterestRate
)

/*
* - The selected installment will be the one with the highest `NumberOfInstallments`;
* - If there is no 'interest-free' installments, the normal installments will be analyzed.
*/
const installment = (isEmpty(noInterestRateInstallments)
? installments
: noInterestRateInstallments
).reduce(
(previous, current) =>
previous.NumberOfInstallments > current.NumberOfInstallments
? previous
: current
)

const formattedInstallmentPrice = formatNumber(
installment.Value,
currencyOptions
)

const [installmentsElement, installmentPriceElement, timesElement] = [
installment.NumberOfInstallments,
formattedInstallmentPrice,
<span key="times">&times;</span>,
].map((element, index) => (
<span className="vtex-price-installments__value" key={index}>
{element}
</span>
))

return (
<div className="vtex-price-installments__container">
<div className="vtex-price-installments dib">
{showLabels ? (
<FormattedMessage
id="pricing.installment-display"
values={{
installments: installmentsElement,
installmentPrice: installmentPriceElement,
times: timesElement,
}}
/>
) : (
<span>
{installmentsElement} {timesElement} {installmentPriceElement}
</span>
)}
{!installment.InterestRate && (
<span className="pl1">
<FormattedMessage id="pricing.interest-free" />
</span>
)}
</div>
</div>
)
}
}

Installments.propTypes = {
/** Product installments to be displayed */
installments: PricePropTypes.installments,
/** Pages editor config to display labels */
showLabels: PropTypes.bool.isRequired,
/** react-intl function to format the prices*/
formatNumber: PropTypes.func.isRequired,
/** Options to be passe to the formatNumber function*/
currencyOptions: PropTypes.shape({
style: PropTypes.string.isRequired,
currency: PropTypes.string.isRequired,
minimumFractionDigits: PropTypes.number.isRequired,
maximumFractionDigits: PropTypes.number.isRequired,
}).isRequired,
}
167 changes: 53 additions & 114 deletions react/components/ProductPrice/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import './global.css'

import PropTypes from 'prop-types'
import { isEmpty, isNil } from 'ramda'
import { isNil } from 'ramda'
import React, { Component } from 'react'
import ContentLoader from 'react-content-loader'
import { FormattedMessage, injectIntl } from 'react-intl'

import PricePropTypes from './propTypes'
import Installments from './Installments'

/**
* The Price component. Shows the prices information of the Product Summary.
Expand All @@ -18,42 +19,6 @@ class Price extends Component {

static propTypes = PricePropTypes

static Loader = (loaderProps = {}) => (
<div className="vtex-price vtex-price-loader">
<ContentLoader
style={{
width: '100%',
height: '100%',
}}
height="100%"
width="100%"
{...loaderProps}>
<rect
height="0.75em"
width="50%"
x="25%"
{...loaderProps['vtex-price-list__container--loader']}
/>
<rect {...loaderProps['vtex-price-selling__label--loader']} />
<rect
height="1em"
width="70%"
x="15%"
y="1.25em"
{...loaderProps['vtex-price-selling--loader']}
/>
<rect
height="0.75em"
width="80%"
x="10%"
y="2.75em"
{...loaderProps['vtex-price-installments--loader']}
/>
<rect {...loaderProps['vtex-price-savings--loader']} />
</ContentLoader>
</div>
)

static defaultProps = {
showListPrice: true,
showLabels: true,
Expand All @@ -68,77 +33,6 @@ class Price extends Component {
maximumFractionDigits: 2,
}

getInstallmentsNode() {
const {
installments,
showLabels,
intl: { formatNumber },
} = this.props

if (!installments || isEmpty(installments)) {
return null
}

const noInterestRateInstallments = installments.filter(
installment => !installment.InterestRate
)

/*
* - The selected installment will be the one with the highest `NumberOfInstallments`;
* - If there is no 'interest-free' installments, the normal installments will be analyzed.
*/
const installment = (isEmpty(noInterestRateInstallments)
? installments
: noInterestRateInstallments
).reduce(
(previous, current) =>
previous.NumberOfInstallments > current.NumberOfInstallments
? previous
: current
)

const formattedInstallmentPrice = formatNumber(
installment.Value,
this.currencyOptions
)

const [installmentsElement, installmentPriceElement, timesElement] = [
installment.NumberOfInstallments,
formattedInstallmentPrice,
<span key="times">&times;</span>,
].map((element, index) => (
<span className="vtex-price-installments__value" key={index}>
{element}
</span>
))

return (
<div className="vtex-price-installments__container">
<div className="vtex-price-installments dib">
{showLabels ? (
<FormattedMessage
id="pricing.installment-display"
values={{
installments: installmentsElement,
installmentPrice: installmentPriceElement,
times: timesElement,
}}
/>
) : (
<span>
{installmentsElement} {timesElement} {installmentPriceElement}
</span>
)}
{!installment.InterestRate && (
<span className="pl1">
<FormattedMessage id="pricing.interest-free" />
</span>
)}
</div>
</div>
)
}

render() {
const {
sellingPrice,
Expand All @@ -147,11 +41,13 @@ class Price extends Component {
showInstallments,
showLabels,
showSavings,
installments,
styles,
intl: { formatNumber },
} = this.props

if ((showListPrice && isNil(listPrice)) || isNil(sellingPrice)) {
return <Price.Loader {...this.props.styles} />
return <Price.Loader {...styles} />
}

const differentPrices = showListPrice && sellingPrice !== listPrice
Expand Down Expand Up @@ -180,7 +76,13 @@ class Price extends Component {
{formatNumber(sellingPrice, this.currencyOptions)}
</div>
</div>
{showInstallments && this.getInstallmentsNode()}
{showInstallments &&
<Installments
installments={installments}
showLabels={showLabels}
formatNumber={formatNumber}
currencyOptions={this.currencyOptions}
/>}
{differentPrices &&
showSavings && (
<div className="vtex-price-savings__container">
Expand All @@ -202,9 +104,46 @@ class Price extends Component {
}
}

const priceComponent = injectIntl(Price)

priceComponent.schema = {
Price.Loader = (loaderProps = {}) => (
<div className="vtex-price vtex-price-loader">
<ContentLoader
style={{
width: '100%',
height: '100%',
}}
height="100%"
width="100%"
{...loaderProps}>
<rect
height="0.75em"
width="50%"
x="25%"
{...loaderProps['vtex-price-list__container--loader']}
/>
<rect {...loaderProps['vtex-price-selling__label--loader']} />
<rect
height="1em"
width="70%"
x="15%"
y="1.25em"
{...loaderProps['vtex-price-selling--loader']}
/>
<rect
height="0.75em"
width="80%"
x="10%"
y="2.75em"
{...loaderProps['vtex-price-installments--loader']}
/>
<rect {...loaderProps['vtex-price-savings--loader']} />
</ContentLoader>
</div>
)


const priceWithIntel = injectIntl(Price)

priceWithIntel.schema = {
title: 'editor.productPrice.title',
description: 'editor.productPrice.description',
type: 'object',
Expand Down Expand Up @@ -236,4 +175,4 @@ priceComponent.schema = {
},
}

export default priceComponent
export default priceWithIntel
2 changes: 1 addition & 1 deletion react/components/ProductPrice/propTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { intlShape } from 'react-intl'

export default {
/** Product selling price */
sellingPrice: PropTypes.number.isRequired,
sellingPrice: PropTypes.number,
/** Product list price */
listPrice: PropTypes.number,
/** Set visibility of list price */
Expand Down

0 comments on commit 7992154

Please sign in to comment.