Add support for package payment methods and basic checkout proccess

This commit is contained in:
Almira Krdzic
2018-08-29 07:56:37 +02:00
parent 5ac3bfff36
commit 438d92e16e
35 changed files with 1600 additions and 309 deletions

View File

@@ -22,12 +22,13 @@ class CoMarketNavContainer extends Component {
render() {
return (
<Row className="co-market-nav">
<Col xl="4" lg="3" md="3" sm="12" xs="12" className="co-market-nav-buttons">
<Col className="col-auto co-market-nav-buttons">
<div className="co-market-nav-div">
{coMarketTexts.labels.NEW_PRODUCTS}
</div>
<div className="wiaas-divider"></div>
</Col>
<Col xl="4" lg="4" md="4" xs="12" className="search-layer">
<Col className="search-layer">
<div className="co-market-nav-div">
<i className="search-package-icon fa fa-search" aria-hidden="true"></i>
<Input className="wiaas-input" onChange={this.handleSearchChange} value={this.state.searchValue} placeholder={coMarketTexts.labels.SEARCH_PACKAGE}/>

View File

@@ -54,14 +54,16 @@ class CoMarketPackageDetailsContainer extends Component {
<Row>
<Col xl="6" lg="5" md="12" xs="12">
<PackageInfo
packageInfo={selectedPackage.packageInfo}
name={selectedPackage.name}
reference={selectedPackage.reference}
shortDescription={selectedPackage.shortDescription}
country={selectedPackage.country}
countryCode={selectedPackage.countryCode}
documents={selectedPackage.documents} />
</Col>
<Col xl="6" lg="7" md="12" xs="12">
<div id="shop-package-buy-info">
<PackagePrice
country={selectedPackage.country} />
{
selectedPackage.groups && Object.keys(selectedPackage.groups).length > 0 && selectedAgreement &&
<PackageOptions
@@ -76,14 +78,16 @@ class CoMarketPackageDetailsContainer extends Component {
}
<AgreementOptions
prices={selectedPackage.prices}
country={selectedPackage.country}/>
<Button id="add-to-cart-btn"
className="add-to-cart-btn"
onClick={this.handleAddToCart}
color="secondary">
<i className="fa fa-shopping-cart" aria-hidden="true"></i>
{' '}{coMarketTexts.buttons.ADD_TO_CART}
</Button>
currency={selectedPackage.currency}/>
<Row className="justify-content-end" style={{ marginTop: 30 }}>
<Button id="add-to-cart-btn"
className="add-to-cart-btn"
onClick={this.handleAddToCart}
color="secondary">
<i className="fa fa-shopping-cart" aria-hidden="true"></i>
{' '}{coMarketTexts.buttons.ADD_TO_CART}
</Button>
</Row>
{messages && <span>{messages[0].message}</span>}
</div>
</Col>

View File

@@ -1,6 +1,6 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {Label, Popover, PopoverBody, Input, Col} from 'reactstrap';
import {Label, Popover, PopoverBody, Input, Col, Row} from 'reactstrap';
import {selectAgreement} from '../../../actions/coMarket/coMarketPackageDetailsActions';
import PriceHelper from '../../../helpers/coMarket/PriceHelper';
import {coMarketTexts} from '../../../constants/coMarketConstants';
@@ -35,49 +35,39 @@ class AgreementOptionItem extends Component {
}
render() {
const {price, selectedAgreement, country} = this.props;
const {price, selectedAgreement, currency} = this.props;
return (
<Col xl="4" lg="4" md="6" xs="6" className="option-value">
<div className={'option-selection ' + this.getClass(selectedAgreement, price)}>
<Label check>
<Row
className={`option-selection ${this.getClass(selectedAgreement, price)}`}
>
<Label check className="row flex-grow-1 no-wrap">
<Col className="d-flex align-items-center">
<Input type="radio"
name="price-type"
onChange={this.handleOptionChange}
checked={selectedAgreement.idPaymentType === price.idPaymentType}
value={price.idPaymentType}
className="price-type-option"/>
<div className="option-name">{price.payType}</div>
<div className="option-prices">
<table className="price-table option-price-table">
<thead>
<tr>
<th>{coMarketTexts.labels.ON_DELIVERY}</th>
<th>{coMarketTexts.labels.MONTHLY}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{price.fixedExtra.toLocaleString()} {country.currency}</td>
<td>
{
priceHelper.hasRecurrentPrice(price)
? <div className="option-value-text monthly-price">
{priceHelper.sumPrices([price.recurentExtra, price.servicesExtra]).toLocaleString()} {country.currency}
</div>
: <div className="option-value-text monthly-price"> 0 </div>
}
</td>
</tr>
</tbody>
</table>
</div>
</Label>
<i className="price-info-btn fa fa-info-circle"
aria-hidden="true"
id={'info-additonal-' + price.idPaymentType}
onClick={this.toggle}></i>
</div>
<span className="option-name">{price.payType}</span>
</Col>
<Col className="d-flex align-items-center">
<span>{price.fixedExtra.toLocaleString()} {currency}</span>
</Col>
<Col className="d-flex align-items-center">
<span className="option-value-text monthly-price">
{
priceHelper.hasRecurrentPrice(price)
? `${priceHelper.sumPrices([price.recurentExtra, price.servicesExtra]).toLocaleString()} ${currency}`
: '0'
}
</span>
</Col>
</Label>
<i className="price-info-btn fa fa-info-circle d-flex align-items-center"
aria-hidden="true"
id={'info-additonal-' + price.idPaymentType}
onClick={this.toggle}></i>
<Popover placement="bottom"
isOpen={this.state.popoverOpen}
target={'info-additonal-' + price.idPaymentType}
@@ -90,7 +80,7 @@ class AgreementOptionItem extends Component {
price.recurentExtra > 0 &&
<div className="package-price-recurrent">
<span className="price-info-title">{coMarketTexts.labels.RECURRENT_PRICE}: </span>
{(price.recurentExtra).toLocaleString()} {country.currency} / {price.periodUnit}
{(price.recurentExtra).toLocaleString()} {currency} / {price.periodUnit}
{
price.packagePayPeriod > 0 &&
<span>
@@ -103,7 +93,7 @@ class AgreementOptionItem extends Component {
price.servicesExtra > 0 &&
<div className="services-price-recurrent">
<span className="price-info-title">{coMarketTexts.labels.SERVICE_PRICE}: </span>
{(price.servicesExtra).toLocaleString()} {country.currency} / {price.periodUnit}
{(price.servicesExtra).toLocaleString()} {currency} / {price.periodUnit}
{
price.servicesContractPeriod > 0 &&
<span>
@@ -115,7 +105,7 @@ class AgreementOptionItem extends Component {
</div>
</PopoverBody>
</Popover>
</Col>
</Row>
);
}
}

View File

@@ -1,24 +1,86 @@
import React, {Component} from 'react';
import {Row} from 'reactstrap';
import {Row, Col} from 'reactstrap';
import AgreementOptionItemContainer from './AgreementOptionItemContainer.jsx';
import {coMarketTexts} from '../../../constants/coMarketConstants';
import {connect} from "react-redux";
class AgreementOptions extends Component {
constructor(props) {
super(props);
this.getFinalPrice = this.getFinalPrice.bind(this);
this.filterByAgreement = this.filterByAgreement.bind(this);
}
filterByAgreement(price) {
return price.idPaymentType === this.props.selectedAgreement.idPaymentType;
}
getExtra(selected, priceType) {
const extraPriceObj = selected.prices.find(this.filterByAgreement);
const extraPrice = extraPriceObj ? extraPriceObj[priceType] : 0;
return extraPrice;
}
getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, priceType) {
let price = selectedAgreement ? selectedAgreement[priceType] : 0;
if(selectedAgreement && selectedOptions) {
Object.keys(selectedOptions).forEach((idGroup) => {
price += this.getExtra(selectedOptions[idGroup], priceType);
});
}
if(selectedAgreement && selectedAdditionals) {
selectedAdditionals.forEach((additional) => {
price += this.getExtra(additional, priceType);
});
}
return price;
}
render() {
const {prices, country} = this.props;
const {prices, currency, selectedAgreement, selectedOptions, selectedAdditionals} = this.props;
return (
<div className="shop-package-options">
<h6 className="shop-package-label options-header">{coMarketTexts.labels.AGREEMENT_OPTIONS}:</h6>
<Row>
<div className="shop-package-pricing">
<Row className="justify-content-end">
<Col className="col-4">
<h6 className="shop-package-label options-header">{coMarketTexts.labels.ON_DELIVERY}</h6>
</Col>
<Col className="col-4">
<h6 className="shop-package-label options-header">{coMarketTexts.labels.MONTHLY}</h6>
</Col>
</Row>
<div className="shop-package-options">
{
prices && prices.map((price) => {
return <AgreementOptionItemContainer key={'agreement-' + price.idPaymentType} country={country} price={price}/>
return (<AgreementOptionItemContainer key={'agreement-' + price.idPaymentType} currency={currency} price={price}/>)
})
}
</div>
<Row className="justify-content-end shop-package-calculated-price">
<Col>
<h6>Price:</h6>
</Col>
<Col className="col-4">
{this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'fixedExtra').toLocaleString()} {currency}
</Col>
<Col className="col-4">
{(this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'recurentExtra')
+ this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'servicesExtra')).toLocaleString()}
{' '}{currency}
</Col>
</Row>
</div>
);
}
}
export default AgreementOptions;
const mapStateToProps = (state) => ({
selectedAgreement: state.coMarketPackageDetailsReducer.selectedAgreement,
selectedOptions: state.coMarketPackageDetailsReducer.selectedOptions,
selectedAdditionals: state.coMarketPackageDetailsReducer.selectedAdditionals
});
export default connect(mapStateToProps) (AgreementOptions);

View File

@@ -14,28 +14,26 @@ class PackageInfo extends Component {
}
render() {
const {packageInfo, documents} = this.props;
const { name, reference, shortDescription, country, countryCode, documents } = this.props;
return (
<div id="shop-package-general-info" className="shop-package-general-info">
{ packageInfo &&
<span>
<Col lg="12"
className="shop-package-title"><h4>{packageInfo.name}</h4></Col>
<Col lg="12"
className="shop-package-reference"><h6>{packageInfo.reference}</h6></Col>
<Col lg="12"
dangerouslySetInnerHTML={{__html: packageInfo.shortDescription}}
className="shop-package-full-description"></Col>
<Col lg="12"
className="shop-package-details-country">
<div className="shop-package-label">{coMarketTexts.labels.AVAILABLE_IN}:</div>
<div className="shop-package-text">
{packageInfo.country} <span className={'flag-icon flag-icon-' + packageInfo.countryCode}></span>
</div>
</Col>
</span>
}
<span>
<Col lg="12"
className="shop-package-title"><h4>{name}</h4></Col>
<Col lg="12"
className="shop-package-reference"><h6>{reference}</h6></Col>
<Col lg="12"
dangerouslySetInnerHTML={{__html: shortDescription}}
className="shop-package-full-description"></Col>
<Col lg="12"
className="shop-package-details-country">
<div className="shop-package-label">{coMarketTexts.labels.AVAILABLE_IN}:</div>
<div className="shop-package-text">
{country} <span className={'flag-icon flag-icon-' + countryCode}></span>
</div>
</Col>
</span>
{
documents && documents.length > 0 &&
<Col lg="12"

View File

@@ -39,7 +39,7 @@ class PackagePrice extends Component {
}
render() {
const {country, selectedAgreement, selectedOptions, selectedAdditionals} = this.props;
const {currency, selectedAgreement, selectedOptions, selectedAdditionals} = this.props;
return (
<div className="selection-price">
@@ -55,12 +55,12 @@ class PackagePrice extends Component {
<tbody>
<tr>
<td>
{this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'fixedExtra').toLocaleString()} {country.currency}
{this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'fixedExtra').toLocaleString()} {currency}
</td>
<td>
{(this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'recurentExtra')
+ this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'servicesExtra')).toLocaleString()}
{' '}{country.currency}
{' '}{currency}
</td>
</tr>
</tbody>

View File

@@ -11,13 +11,14 @@ class ShopItem extends Component {
render() {
const {shopPackage, idCommercialLead} = this.props;
return (
<Col xl="3" lg="4" md="6" sm="12" xs="12">
<Col xl="3" lg="3" md="4" sm="6" xs="12">
<Card className="shop-package-item">
<div
className="shop-image-photo"
style={{'backgroundImage': `url(${shopPackage.image})`}}
/>
<img
className="card-img-top shop-image-photo"
src={shopPackage.image}
alt="Card image cap"/>
<CardBody>
<CardTitle className="shop-package-title">
<Link to={`/co-market/${idCommercialLead}/${shopPackage.id}`}>

View File

@@ -56,8 +56,18 @@
margin-left: 0.2rem;
}
.wiaas-box-header {
padding: 1rem;
align-items: center;
display: flex;
.wiaas-box-visibility-icon {
top: 50%;
transform: translateY(-50%);
}
}
.co-market-nav {
font-size: $font-size-msmall;
font-size: $font-size-small;
text-align: left;
color: $warmGreyColor;
vertical-align: middle;
@@ -77,17 +87,20 @@
.search-layer div{
position: relative;
flex-grow: 1;
padding-right: 1rem;
}
.wiaas-input {
border-radius: 3.125rem;
border-radius: 4rem;
background-color: $whiteColor;
border: solid 1px $borderColor;
padding: 0.2rem 1.4rem;
font-size: $font-size-xsmal;
padding: 0.2rem 3rem;
font-size: $font-size-small;
font-weight: 300;
text-align: left;
color: $warmGreyColor;
height: 2.2rem;
}
input:focus {
@@ -96,16 +109,15 @@
.search-package-icon {
position: absolute;
font-size: $font-size-xsmal;
left: 0.4rem;
top: 0.3rem;
font-size: $font-size-normal;
left: 1.6rem;
top: 0.6rem;
color: $warmGreyColor;
}
.shop-image-photo{
width:100%;
height:129px;
background-size: cover;
object-fit: cover;
}
}

View File

@@ -55,6 +55,16 @@
#shop-package-buy-info{
padding: 2rem;
.shop-package-pricing {
> div.row {
margin: 0 32px 0 0;
}
}
.shop-package-calculated-price {
font-weight: $font-weight;
}
.shop-package-options{
margin: 1rem 0;
border-bottom: 2px solid $title-color;
@@ -71,7 +81,7 @@
.price-info-btn {
color: $info-color;
cursor: pointer;
margin-left: 0.2rem;
padding: 0.5rem;
}
.add-to-cart-btn {
@@ -83,32 +93,39 @@
}
.selected-option {
font-weight: $font-weight;
background: $hoverColor;
border-radius: $box-radius;
}
.option-selection {
display: inline-block;
vertical-align: top;
padding: 0.5rem;
padding: 0.5rem 0;
margin: 0;
flex-wrap: nowrap;
> label {
cursor: pointer;
margin: 0;
flex-wrap: nowrap;
}
input.price-type-option {
position: relative;
margin: 0 10px 0 0;
}
span.option-name {
font-size: $font-size-small;
}
}
.option-selection:hover {
background: $footer-background;
color: $whiteColor;
border-radius: $box-radius;
}
.option-selection:hover .price-info-btn {
color: $whiteColor;
}
.option-name {
font-size: $font-size-msmall;
height: 2rem;
}
.option-description {
padding-top: 0.5rem;
font-size: $font-size-msmall;
@@ -131,11 +148,6 @@
font-weight: bold;
}
.option-prices {
margin-top: 0.5rem;
border-radius: $box-radius;
}
.price-table {
width: 8rem;
}