initial docker setup

This commit is contained in:
GotPPay
2018-06-14 16:49:28 +02:00
parent bc80b7342e
commit b5f87f27f8
3023 changed files with 985078 additions and 1 deletions

View File

@@ -0,0 +1,27 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {Container} from 'reactstrap';
import CoMarketPackagesContainer from './CoMarketPackagesContainer.jsx';
import CoMarketPackageDetailsContainer from './CoMarketPackageDetailsContainer.jsx';
import {setPackageFromUrl} from '../../actions/coMarket/coMarketActions';
import './style/CoMarket.css'
class CoMarketContainer extends Component {
componentDidMount(){
this.props.dispatch(setPackageFromUrl(this.props.match.params.idPackage));
}
render() {
const urlParams = this.props.match.params;
return (<Container fluid={true} id="co-market-container">
{
urlParams.idPackage ?
<CoMarketPackageDetailsContainer idPackage={urlParams.idPackage} idCommercialLead={urlParams.idCommercialLead}/> :
<CoMarketPackagesContainer/>
}
</Container>);
}
}
export default connect()(CoMarketContainer);

View File

@@ -0,0 +1,45 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {Row, Col, Input} from 'reactstrap';
import {fetchShopPackages} from '../../actions/coMarket/coMarketPackagesActions';
import {coMarketTexts} from '../../constants/coMarketConstants';
class CoMarketNavContainer extends Component {
constructor(props) {
super(props);
this.handleSearchChange = this.handleSearchChange.bind(this);
this.state = {
searchValue : ''
};
}
handleSearchChange(event) {
this.setState({searchValue: event.target.value});
this.props.dispatch(fetchShopPackages(this.props.selectedCommercialLead, event.target.value));
}
render() {
return (
<Row className="co-market-nav">
<Col xl="4" lg="3" md="3" sm="12" xs="12" className="co-market-nav-buttons">
<div className="co-market-nav-div">
{coMarketTexts.labels.NEW_PRODUCTS}
</div>
</Col>
<Col xl="4" lg="4" md="4" xs="12" 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}/>
</div>
</Col>
</Row>
);
}
}
const mapStateToProps = (state) => ({
selectedCommercialLead: state.coMarketPackagesReducer.selectedCommercialLead
});
export default connect(mapStateToProps)(CoMarketNavContainer);

View File

@@ -0,0 +1,109 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {Row, Col, Button} from 'reactstrap';
import WiaasBox from '../../mainComponents/box/WiaasBox.jsx';
import {fetchPackageDetails, addToCart} from '../../actions/coMarket/coMarketPackageDetailsActions';
import PackageInfo from './components/PackageInfo.jsx';
import PackagePrice from './components/PackagePrice.jsx';
import PackageOptions from './components/PackageOptions.jsx';
import AdditionalPackages from './components/AdditionalPackages.jsx';
import AgreementOptions from './components/AgreementOptions.jsx';
import {coMarketTexts} from '../../constants/coMarketConstants';
import './style/CoMarketPackageDetailsContainer.css';
class CoMarketPackageDetailsContainer extends Component {
constructor(props) {
super(props);
this.handleAddToCart = this.handleAddToCart.bind(this);
this.state = {
selectedOptions: {}
};
}
handleAddToCart() {
const addParams = {
selectedPackage: this.props.selectedPackage,
selectedAgreement: this.props.selectedAgreement,
selectedOptions: this.props.selectedOptions,
selectedAdditionals: this.props.selectedAdditionals
};
this.props.dispatch(addToCart(addParams));
}
componentDidMount() {
const {idPackage, idCommercialLead} = this.props;
this.props.dispatch(fetchPackageDetails({idPackage, idCommercialLead}));
}
render() {
const {selectedPackage, selectedAgreement, messages, isLoading} = this.props;
return(
<div id="co-market-package-details">
<Row>
<Col xl="12" lg="12">
<WiaasBox>
{
isLoading &&
<div className="loader">
<i className="fa fa-spinner fa-spin fa-3x" aria-hidden="true"></i>
</div>
}
{
(selectedPackage && !isLoading) &&
<Row>
<Col xl="6" lg="5" md="12" xs="12">
<PackageInfo
packageInfo={selectedPackage.packageInfo}
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
groups={selectedPackage.groups}
country={selectedPackage.country}/>
}
{
selectedPackage.additionalPackages && selectedPackage.additionalPackages.length > 0 && selectedAgreement &&
<AdditionalPackages
additionalPackages={selectedPackage.additionalPackages}
country={selectedPackage.country}/>
}
<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>
{messages && <span>{messages[0].message}</span>}
</div>
</Col>
</Row>
}
</WiaasBox>
</Col>
</Row>
</div>
);
}
}
const mapStateToProps = (state) => ({
selectedPackage: state.coMarketPackageDetailsReducer.selectedPackage,
selectedAgreement: state.coMarketPackageDetailsReducer.selectedAgreement,
selectedOptions: state.coMarketPackageDetailsReducer.selectedOptions,
selectedAdditionals: state.coMarketPackageDetailsReducer.selectedAdditionals,
messages: state.coMarketPackageDetailsReducer.messages,
isLoading: state.coMarketPackageDetailsReducer.isLoading
});
export default connect(mapStateToProps)(CoMarketPackageDetailsContainer);

View File

@@ -0,0 +1,62 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {Row, Col} from 'reactstrap';
import ShopItem from './components/ShopItem.jsx';
import WiaasBox from '../../mainComponents/box/WiaasBox.jsx';
import CoMarketNavContainer from './CoMarketNavContainer.jsx';
import {fetchShopPackages} from '../../actions/coMarket/coMarketPackagesActions';
class CoMarketPackagesContainer extends Component {
componentDidMount() {
this.props.dispatch(fetchShopPackages(this.props.selectedCommercialLead));
}
render() {
const {shopPackages, selectedCommercialLead, isLoading} = this.props;
return (
<div id="co-market-shop">
<Row>
<Col xl="8" lg="8" md="8" sm="12" xs="12">
<WiaasBox id="co-market-big-commercial">
<img className="description-photo" src="https://res.cloudinary.com/co-market/image/upload/v1524472688/Co-Market/CoMarketStartsida_MAIN.jpg" alt="big-commercial"/>
</WiaasBox>
</Col>
<Col xl="4" lg="4" md="4" sm="12" xs="12">
<WiaasBox id="co-market-commercials">
<img alt="wiaas commercial" src="https://res.cloudinary.com/co-market/image/upload/v1524472688/Co-Market/CoMarketStartsida_OFFERCoor.jpg" className="commercial-photo"/>
</WiaasBox>
</Col>
</Row>
<Row>
<Col xl="8" lg="12" md="12">
<WiaasBox id="co-market-packages" customHeader={CoMarketNavContainer}>
<Row>
{
isLoading &&
<Col xl="12" className="loader">
<i className="fa fa-spinner fa-spin fa-3x" aria-hidden="true"></i>
</Col>
}
{
(shopPackages && !isLoading) &&
shopPackages.map((shopPackage, mapKey) => <ShopItem key={shopPackage.idPackage}
idCommercialLead={selectedCommercialLead.value}
shopPackage={shopPackage}/>)
}
</Row>
</WiaasBox>
</Col>
</Row>
</div>
);
}
}
const mapStateToProps = (state) => ({
shopPackages: state.coMarketPackagesReducer.shopPackages,
selectedCommercialLead: state.coMarketPackagesReducer.selectedCommercialLead,
isLoading: state.coMarketPackagesReducer.isLoading
});
export default connect(mapStateToProps)(CoMarketPackagesContainer);

View File

@@ -0,0 +1,131 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {Label, Popover, PopoverBody, Input, Col} from 'reactstrap';
import {selectAdditional, removetAdditional} from '../../../actions/coMarket/coMarketPackageDetailsActions';
import PriceHelper from '../../../helpers/coMarket/PriceHelper';
import {coMarketTexts} from '../../../constants/coMarketConstants';
const priceHelper = new PriceHelper();
class AdditionalPackageItem extends Component {
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.handleOptionChange = this.handleOptionChange.bind(this);
this.isChecked = this.isChecked.bind(this);
this.state = {
popoverOpen: false
};
}
toggle() {
this.setState({
popoverOpen: !this.state.popoverOpen
});
}
handleOptionChange() {
if(!this.isChecked()){
this.props.dispatch(selectAdditional(this.props.additionalPackage))
}else{
this.props.dispatch(removetAdditional(this.props.additionalPackage));
}
}
isChecked() {
return this.props.selectedAdditionals
&& this.props.selectedAdditionals.includes(this.props.additionalPackage);
}
isAvailable() {
return this.props.additionalPackage.prices.find(price => {
return price.idPaymentType === this.props.selectedAgreement.idPaymentType;
});
}
getClass(isChecked) {
return isChecked ?
'selected-option' :
'';
}
formatName(name) {
return name.length > 39 ? name.substring(0, 40) + '...' : name;
}
render() {
const {additionalPackage, country} = this.props;
const isAvailable = this.isAvailable();
const selectedPrice = priceHelper.getSelectedPrice(additionalPackage, this.props.selectedAgreement);
const isChecked = this.isChecked();
return (
<Col xl="4" lg="4" md="6" xs="6" className="option-value">
<div className={'option-selection ' + this.getClass(isChecked)}>
<Label check>
<Input type="checkbox"
onChange={this.handleOptionChange}
name={'package-option-'+ additionalPackage.idAdditionalPackage}
className="package-option-input"/>
<div className="option-name">{this.formatName(additionalPackage.packageName)}</div>
<div className="option-description" dangerouslySetInnerHTML={{__html: additionalPackage.shortDescription}}></div>
{
priceHelper.hasFixedPrice(selectedPrice) &&
<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>{selectedPrice.fixedExtra > 0 ? selectedPrice.fixedExtra.toLocaleString() : 0} {country.currency}</td>
<td>
<div className="option-value-text monthly-price">
{
priceHelper.hasRecurrentPrice(selectedPrice)
? priceHelper.sumPrices([selectedPrice.recurentExtra, selectedPrice.servicesExtra]).toLocaleString() + ' '
: 0
} {country.currency}
</div>
</td>
</tr>
</tbody>
</table>
</div>
}
</Label>
{
!isAvailable &&
<span className="not-available">
({coMarketTexts.labels.NOT_AVAILABLE})
<i className="price-info-btn fa fa-info-circle"
aria-hidden="true"
id={'info-additonal-' + additionalPackage.idAdditionalPackage}
onClick={this.toggle}></i>
</span>
}
</div>
<Popover placement="bottom"
isOpen={this.state.popoverOpen}
target={'info-additonal-' + additionalPackage.idAdditionalPackage}
toggle={this.toggle}>
<PopoverBody>
{coMarketTexts.labels.SELECTION_NOT_AVAILABLE}
</PopoverBody>
</Popover>
</Col>
);
}
}
const mapStateToProps = (state) => ({
selectedAgreement: state.coMarketPackageDetailsReducer.selectedAgreement,
selectedAdditionals: state.coMarketPackageDetailsReducer.selectedAdditionals
});
export default connect(mapStateToProps)(AdditionalPackageItem);

View File

@@ -0,0 +1,26 @@
import React, {Component} from 'react';
import {Row} from 'reactstrap';
import AdditionalPackageItemContainer from './AdditionalPackageItemContainer.jsx';
import {coMarketTexts} from '../../../constants/coMarketConstants';
class AdditionalPackages extends Component {
render() {
const {additionalPackages, country} = this.props;
return (
<div className="shop-package-options">
<h6 className="shop-package-label options-header">{coMarketTexts.labels.ADDITIONAL_PACKAGES}:</h6>
<Row>
{
additionalPackages.map(additionalPackage => {
return <AdditionalPackageItemContainer key={'additonal-' + additionalPackage.idAdditionalPackage}
country={country}
additionalPackage={additionalPackage}/>
})
}
</Row>
</div>
);
}
}
export default AdditionalPackages;

View File

@@ -0,0 +1,127 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {Label, Popover, PopoverBody, Input, Col} from 'reactstrap';
import {selectAgreement} from '../../../actions/coMarket/coMarketPackageDetailsActions';
import PriceHelper from '../../../helpers/coMarket/PriceHelper';
import {coMarketTexts} from '../../../constants/coMarketConstants';
const priceHelper = new PriceHelper();
class AgreementOptionItem extends Component {
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.handleOptionChange = this.handleOptionChange.bind(this);
this.state = {
popoverOpen: false
};
}
toggle() {
this.setState({
popoverOpen: !this.state.popoverOpen
});
}
handleOptionChange() {
this.props.dispatch(selectAgreement(this.props.price));
}
getClass(selectedAgreement, price) {
return selectedAgreement.idPaymentType === price.idPaymentType ?
'selected-option' :
'';
}
render() {
const {price, selectedAgreement, country} = 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>
<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>
<Popover placement="bottom"
isOpen={this.state.popoverOpen}
target={'info-additonal-' + price.idPaymentType}
className="price-info-popover"
container="shop-package-buy-info"
toggle={this.toggle}>
<PopoverBody>
<div>
{
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.packagePayPeriod > 0 &&
<span>
{' '} for {price.packagePayPeriod} {price.periodUnit}
</span>
}
</div>
}
{
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.servicesContractPeriod > 0 &&
<span>
{' '} for {price.servicesContractPeriod} {price.periodUnit} {coMarketTexts.labels.EXTEND} {price.periodUnit} (Max {price.maxContractPeriod} {price.periodUnit})
</span>
}
</div>
}
</div>
</PopoverBody>
</Popover>
</Col>
);
}
}
const mapStateToProps = (state) => ({
selectedAgreement: state.coMarketPackageDetailsReducer.selectedAgreement
});
export default connect(mapStateToProps)(AgreementOptionItem);

View File

@@ -0,0 +1,24 @@
import React, {Component} from 'react';
import {Row} from 'reactstrap';
import AgreementOptionItemContainer from './AgreementOptionItemContainer.jsx';
import {coMarketTexts} from '../../../constants/coMarketConstants';
class AgreementOptions extends Component {
render() {
const {prices, country} = this.props;
return (
<div className="shop-package-options">
<h6 className="shop-package-label options-header">{coMarketTexts.labels.AGREEMENT_OPTIONS}:</h6>
<Row>
{
prices && prices.map((price) => {
return <AgreementOptionItemContainer key={'agreement-' + price.idPaymentType} country={country} price={price}/>
})
}
</Row>
</div>
);
}
}
export default AgreementOptions;

View File

@@ -0,0 +1,20 @@
import React, {Component} from 'react';
class CartIcon extends Component {
render() {
const cartCount = parseInt(this.props.cartCount, 10);
return (
<span className="items-cart-count">
{ cartCount === 0
? <span>Cart is empty</span>
: cartCount === 1
? <span>1 item in cart</span>
: <span>{cartCount} items in cart</span>
}
</span>
);
}
}
export default CartIcon;

View File

@@ -0,0 +1,83 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import Select from 'react-select';
import {fetchShopPackages, fetchShopCommercialLeads, selectCommercialLead} from '../../../actions/coMarket/coMarketPackagesActions';
import {coMarketTexts} from '../../../constants/coMarketConstants';
class CoMarketCatalogSelect extends Component {
constructor(props) {
super(props);
this.handleClChange = this.handleClChange.bind(this);
this.handleSearchChange = this.handleSearchChange.bind(this);
this.state = {
searchValue : ''
};
}
componentDidMount() {
this.props.dispatch(fetchShopCommercialLeads());
if(this.props.commercialLeads && this.props.cartItems && this.props.activeModule==='cart'){
const cl = this.props.commercialLeads.find((cl) => {return cl.idCommercialLead===this.props.cartItems[0].idCommercialLead});
this.props.dispatch(selectCommercialLead(cl));
}
}
componentWillReceiveProps(nextProps){
if(nextProps.activeModule==='cart' && nextProps.commercialLeads && nextProps.cartItems && nextProps.cartItems.length > 0){
const cl = nextProps.commercialLeads.find((cl) => {return cl.idCommercialLead===nextProps.cartItems[0].idCommercialLead});
nextProps.dispatch(selectCommercialLead(cl));
}
if(nextProps.commercialLeads && nextProps.idCommercialLead && nextProps.activeModule === 'co-market'){
const cl = nextProps.commercialLeads.find((cl) => {return cl.idCommercialLead===nextProps.idCommercialLead});
nextProps.dispatch(selectCommercialLead(cl));
}
}
handleClChange(cl) {
this.props.dispatch(selectCommercialLead(cl));
this.props.dispatch(fetchShopPackages(cl));
}
handleSearchChange(event) {
this.setState({searchValue: event.target.value});
this.props.dispatch(fetchShopPackages(this.props.selectedCommercialLead, event.target.value));
}
render() {
const {commercialLeads, selectedCommercialLead, idPackage, activeSubmodule} = this.props;
const isDisabled = (idPackage || this.props.activeModule === 'cart') ? true : false;
return (
<div id="co-market-catalog">
{
commercialLeads && activeSubmodule !== 'orders' &&
<div className="filters co-market-nav-div">
<div className="filter-name">{coMarketTexts.labels.CATALOGUE}:</div>
<Select value={selectedCommercialLead}
name="commercialLead"
className="filter-select"
placeholder={coMarketTexts.labels.SELECT_CL}
options={commercialLeads}
disabled={isDisabled}
clearable={false}
onChange={(cl) => {this.handleClChange(cl)}}
/>
</div>
}
</div>
);
}
}
const mapStateToProps = (state) => ({
commercialLeads: state.coMarketPackagesReducer.commercialLeads,
selectedCommercialLead: state.coMarketPackagesReducer.selectedCommercialLead,
idPackage: state.coMarketReducer.idPackage,
cartItems: state.cartReducer.cartItems,
activeSubmodule: state.pageReducer.activeSubmodule
});
export default connect(mapStateToProps)(CoMarketCatalogSelect);

View File

@@ -0,0 +1,61 @@
import React, {Component} from 'react';
import {Col} from 'reactstrap';
import {API_SERVER} from '../../../config';
import FileDownloader from '../../../helpers/FileDownloader';
import {coMarketTexts} from '../../../constants/coMarketConstants';
const fileHandler = new FileDownloader();
class PackageInfo extends Component {
downloadDocument(document){
const fileUrl = `${API_SERVER}/utils/api/downloadFile?idDocument=${document.idDocument}&fileName=${document.documentName}.${document.extension}`
const fileName = document.documentName + '.' + document.extension;
fileHandler.download(fileUrl, fileName);
}
render() {
const {packageInfo, 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>
}
{
documents && documents.length > 0 &&
<Col lg="12"
className="shop-package-details-documents">
<div className="shop-package-label">{coMarketTexts.labels.DOCUMENTS}:</div>
{
documents.map((document) =>
<div key={document.idDocument}>
<span className="document-link"
onClick={() => {this.downloadDocument(document)}}>
<i className="fa fa-file" aria-hidden="true"></i> {document.documentName} ({document.extension})
</span>
</div>
)
}
</Col>
}
</div>
);
}
}
export default PackageInfo;

View File

@@ -0,0 +1,123 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {Label, Popover, PopoverBody, Input, Col} from 'reactstrap';
import {selectOption} from '../../../actions/coMarket/coMarketPackageDetailsActions';
import PriceHelper from '../../../helpers/coMarket/PriceHelper';
import {coMarketTexts} from '../../../constants/coMarketConstants';
const priceHelper = new PriceHelper();
class PackageOptionItem extends Component {
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.handleOptionChange = this.handleOptionChange.bind(this);
this.state = {
popoverOpen: false
};
}
toggle() {
this.setState({
popoverOpen: !this.state.popoverOpen
});
}
handleOptionChange() {
this.props.dispatch(selectOption(this.props.idGroup, this.props.option));
}
isChecked() {
return this.props.selectedOptions
&& this.props.selectedOptions[this.props.idGroup]
&& this.props.selectedOptions[this.props.idGroup].idOptionPackage === this.props.option.idOptionPackage;
}
getClass(isChecked) {
return isChecked ?
'selected-option' :
'';
}
formatName(name) {
return name.length > 39 ? name.substring(0, 40) + '...' : name;
}
render() {
const {idGroup, option, country} = this.props;
const selectedPrice = this.props.selectedAgreement ? priceHelper.getSelectedPrice(option, this.props.selectedAgreement) : null;
const isChecked = this.isChecked();
return (
<Col xl="4" lg="4" md="6" xs="6" className="option-value">
<div className={'form-check-inline option-selection ' + this.getClass(isChecked)}>
<Label check>
<Input type="radio"
name={'package-option-'+ idGroup}
className="package-option-input"
onChange={this.handleOptionChange}
checked={isChecked}
value={option.idOptionPackage}/>
<div className="option-name">{this.formatName(option.optionName)}</div>
<div className="option-description" dangerouslySetInnerHTML={{__html: option.shortDescription}}></div>
{
priceHelper.hasFixedPrice(selectedPrice) &&
<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>{selectedPrice.fixedExtra && selectedPrice.fixedExtra.toLocaleString() + ' ' + country.currency} </td>
<td>
{
priceHelper.hasRecurrentPrice(selectedPrice) ?
<div className="option-value-text monthly-price">
{priceHelper.sumPrices([selectedPrice.recurentExtra, selectedPrice.servicesExtra]).toLocaleString()} {country.currency}
</div>
: <div className="option-value-text monthly-price"> 0 </div>
}
</td>
</tr>
</tbody>
</table>
</div>
}
</Label>
{
!selectedPrice &&
<Label>
<div className="not-available">
({coMarketTexts.labels.NOT_AVAILABLE})
<i className="price-info-btn fa fa-info-circle"
aria-hidden="true"
id={'info-option-' + idGroup + '-' + option.idOptionPackage}
onClick={this.toggle}></i>
</div>
</Label>
}
</div>
<Popover placement="bottom"
isOpen={this.state.popoverOpen}
target={'info-option-' + idGroup + '-' + option.idOptionPackage}
toggle={this.toggle}>
<PopoverBody>
{coMarketTexts.labels.SELECTION_NOT_AVAILABLE}
</PopoverBody>
</Popover>
</Col>
);
}
}
const mapStateToProps = (state) => ({
selectedAgreement: state.coMarketPackageDetailsReducer.selectedAgreement,
selectedOptions: state.coMarketPackageDetailsReducer.selectedOptions
});
export default connect(mapStateToProps)(PackageOptionItem);

View File

@@ -0,0 +1,35 @@
import React, {Component} from 'react';
import {Row} from 'reactstrap';
import PackageOptionItemContainer from './PackageOptionItemContainer.jsx';
import {coMarketTexts} from '../../../constants/coMarketConstants';
class PackageOptions extends Component {
render() {
const {groups, country} = this.props;
return (
<div className="shop-package-options">
<h6 className="shop-package-label options-header">{coMarketTexts.labels.PACKAGE_OPTIONS}</h6>
{
Object.keys(groups).map(groupKey => {
const group = groups[groupKey];
return <div key={'group-' + group.idGroup} className="package-option">
<h6 className="shop-package-label"> {group.groupName}:</h6>
<Row>
{
group.options.map(option => {
return <PackageOptionItemContainer key={'option-' + group.idGroup + option.idOptionPackage}
option={option}
country={country}
idGroup={group.idGroup}/>
})
}
</Row>
</div>
})
}
</div>
);
}
}
export default PackageOptions;

View File

@@ -0,0 +1,80 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {coMarketTexts} from '../../../constants/coMarketConstants';
class PackagePrice 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 {country, selectedAgreement, selectedOptions, selectedAdditionals} = this.props;
return (
<div className="selection-price">
{
selectedAgreement &&
<table className="price-table main-price">
<thead>
<tr>
<th>{coMarketTexts.labels.ON_DELIVERY}</th>
<th>{coMarketTexts.labels.MONTHLY}</th>
</tr>
</thead>
<tbody>
<tr>
<td>
{this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'fixedExtra').toLocaleString()} {country.currency}
</td>
<td>
{(this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'recurentExtra')
+ this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'servicesExtra')).toLocaleString()}
{' '}{country.currency}
</td>
</tr>
</tbody>
</table>
}
</div>
);
}
}
const mapStateToProps = (state) => ({
selectedAgreement: state.coMarketPackageDetailsReducer.selectedAgreement,
selectedOptions: state.coMarketPackageDetailsReducer.selectedOptions,
selectedAdditionals: state.coMarketPackageDetailsReducer.selectedAdditionals
});
export default connect(mapStateToProps)(PackagePrice);

View File

@@ -0,0 +1,45 @@
import React, {Component} from 'react';
import {Link} from 'react-router-dom';
import { Col, Card, CardBody, CardTitle, CardSubtitle, Button} from 'reactstrap';
import {coMarketTexts} from '../../../constants/coMarketConstants';
class ShopItem extends Component {
getShopItemPackageTitle(name) {
return name.length > 40 ? name.substring(0, 40) + '...' : name;
}
render() {
const {shopPackage, idCommercialLead} = this.props;
return (
<Col xl="3" lg="4" md="6" sm="12" xs="12">
<Card className="shop-package-item">
<div className="shop-image-photo" style={{'background-image': 'url("'+(shopPackage.photo || 'static/img/no-photo-package.jpg') +'")'}}></div>
<CardBody>
<CardTitle className="shop-package-title">
<Link to={`/co-market/${idCommercialLead}/${shopPackage.idPackage}`}>
{this.getShopItemPackageTitle(shopPackage.name)}
</Link>
</CardTitle>
<CardSubtitle className="shop-package-reference">
{shopPackage.reference}
</CardSubtitle>
<div className="shop-package-country">
{coMarketTexts.labels.AVAILABLE_IN}: {shopPackage.country}
<span className={'flag-icon flag-icon-' + shopPackage.countryCode}></span>
</div>
<div className="shop-package-details-btn-layer">
<Link id={'shop-package-details-' + shopPackage.idPackage} to={`/co-market/${idCommercialLead}/${shopPackage.idPackage}`}>
<Button className="shop-package-details-btn">{coMarketTexts.buttons.DETAILS}</Button>
</Link>
</div>
</CardBody>
</Card>
</Col>
);
}
}
export default ShopItem;

View File

@@ -0,0 +1,175 @@
@import '../../../styleConstants.scss';
#co-market-shop {
.shop-package-title {
font-size: 1rem;
height: 2rem;
}
.shop-package-title a {
font-size: $font-size-msmall;
font-weight: $font-weight;
text-align: left;
color: $header-background;
}
.shop-package-reference {
font-size: $font-size-xsmal;
font-weight: $font-weight;
text-align: left;
color: $warmGreyColor;
}
.shop-package-country {
display: inline-block;
width: 50%;
font-size: $font-size-xsmal;
text-align: left;
color: $warmGreyColor;
}
.shop-package-details-btn-layer{
display: inline-block;
width: 50%;
text-align: right;
}
.shop-package-details-btn{
border-radius: 50px;
background-color: $whiteColor;
border: solid 0.7px $borderColor;
color: $darkBlue;
font-weight: $font-weight;
font-size: $font-size-xsmal;
cursor: pointer;
}
.shop-package-item{
margin-top: 1rem;
border-radius: 4px;
background-color: $whiteColor;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
}
.flag-icon{
border-radius: 2px;
margin-left: 0.2rem;
}
.co-market-nav {
font-size: $font-size-msmall;
text-align: left;
color: $warmGreyColor;
vertical-align: middle;
}
.co-market-nav-buttons{
display: flex;
align-items: center;
color: $header-background;
font-weight: $font-weight;
}
.search-layer{
display:flex;
align-items:center;
}
.search-layer div{
position: relative;
}
.wiaas-input {
border-radius: 3.125rem;
background-color: $whiteColor;
border: solid 1px $borderColor;
padding: 0.2rem 1.4rem;
font-size: $font-size-xsmal;
font-weight: 300;
text-align: left;
color: $warmGreyColor;
}
input:focus {
outline: none;
}
.search-package-icon {
position: absolute;
font-size: $font-size-xsmal;
left: 0.4rem;
top: 0.3rem;
color: $warmGreyColor;
}
.shop-image-photo{
width:100%;
height:129px;
background-size: cover;
}
}
#co-market-big-commercial{
background: $whiteColor;
text-align: center;
.ricoh-text {
color: $ricohRed;
}
.description-photo{
max-width: 100%;
}
}
#co-market-commercials {
background: $whiteColor;
.commercial-photo {
width: 100%;
}
}
#co-market-catalog {
.filter-name {
margin-top: 0.4rem;
font-size: $font-size-normal;
display: inline-block;
margin-right: 0.2rem;
font-weight: $font-weight;
}
.filter-select{
display: inline-block;
width: 21rem;
vertical-align: top;
}
}
@media all and (max-width: 767px) {
.co-market-nav-div {
width: 100%;
text-align: center;
margin: 0.5rem 0;
font-size: $font-size-normal;
}
.wiaas-input {
font-size: $font-size-normal;
}
#co-market-shop {
.shop-package-title a {
font-size: $font-size-big;
}
.shop-package-reference, .shop-package-country{
font-size: $font-size-normal;
}
.shop-package-details-btn{
font-size: $font-size-xbig;
}
}
}

View File

@@ -0,0 +1,159 @@
@import '../../../styleConstants.scss';
#co-market-package-details{
background: $whiteColor;
border-radius: $box-radius;
}
#shop-package-general-info {
padding: 2rem;
.shop-package-title {
font-size: $font-size-big;
text-align: center;
font-weight: $font-weight;
}
.shop-package-reference {
margin-bottom: 5%;
text-align: center;
font-weight: $font-weight;
font-size: $font-size-normal;
color: $darkGreyColor;
}
.shop-package-full-description {
font-size: $font-size-normal;
overflow: auto;
min-height: 15rem;
max-height: 30rem;
}
.shop-package-label{
display: inline-block;
}
.shop-package-text {
display: inline-block;
margin-left: 1rem;
}
.shop-package-details-country{
margin-top: 1rem;
}
.shop-package-details-documents{
margin-top: 1rem;
}
.document-link{
color: #33425b;
cursor: pointer;
}
}
#shop-package-buy-info{
padding: 2rem;
.shop-package-options{
margin: 1rem 0;
border-bottom: 2px solid $title-color;
}
.not-available {
margin-top: 1rem;
margin-left: 0.2rem;
color: $not-available-status-color;
font-weight: $font-weight;
font-size: $font-size-msmall;
}
.price-info-btn {
color: $info-color;
cursor: pointer;
margin-left: 0.2rem;
}
.add-to-cart-btn {
cursor: pointer;
color: $darkGreyColor;
background-color: $whiteColor;
border-color:$warmGreyColor;
}
.selected-option {
font-weight: $font-weight;
background: $hoverColor;
border-radius: $box-radius;
}
.option-selection {
display: inline-block;
vertical-align: top;
padding: 0.5rem;
}
.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;
height: 2rem;
}
.price-info-popover {
max-width: 50rem;
}
.recurent-total-price{
font-size: $font-size-msmall;
}
.selection-price{
background: $hoverColor;
display: inline-block;
border-radius: $box-radius;
font-size: $font-size-big;
font-weight: bold;
}
.option-prices {
margin-top: 0.5rem;
border-radius: $box-radius;
}
.price-table {
width: 8rem;
}
.main-price {
width: auto;
}
.price-table th{
padding: 0.5rem;
}
.price-table td{
border-top: 1px solid $darkGreyColor;
padding: 0.5rem;
}
.option-price-table{
font-size: $font-size-xsmal;
}
}