initial docker setup
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import React, {Component} from 'react';
|
||||
import InstallationSchedulingForPackages from './components/installationScheduling/InstallationSchedulingForPackages.jsx';
|
||||
|
||||
class InstallationSchedulingContainer extends Component {
|
||||
render() {
|
||||
const {orderPackages, areComponentsDisabled, isInstallationSet, isInstallationInPackage, areAllShippingDatesConfirmed} = this.props.params;
|
||||
|
||||
return (
|
||||
<span>
|
||||
{orderPackages &&
|
||||
orderPackages.map(orderPackage =>
|
||||
<InstallationSchedulingForPackages key={orderPackage.idPackage}
|
||||
orderPackage={orderPackage}
|
||||
areComponentsDisabled={areComponentsDisabled}
|
||||
isInstallationSet={isInstallationSet}
|
||||
isInstallationInPackage={isInstallationInPackage}
|
||||
areAllShippingDatesConfirmed={areAllShippingDatesConfirmed}
|
||||
noOfPackages={orderPackages.length}/>)
|
||||
}
|
||||
</span>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default InstallationSchedulingContainer;
|
||||
78
frontend/src/containers/orders/OrdersContainer.jsx
Normal file
78
frontend/src/containers/orders/OrdersContainer.jsx
Normal file
@@ -0,0 +1,78 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Container, TabContent, TabPane, Nav, NavItem, NavLink, Row, Col} from 'reactstrap';
|
||||
import classnames from 'classnames';
|
||||
import './style/Orders.css';
|
||||
import OrdersDataContainer from './OrdersDataContainer.jsx';
|
||||
import ProcessContainer from './ProcessContainer.jsx';
|
||||
import {orderTexts} from '../../constants/ordersConstants';
|
||||
|
||||
class OrdersContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.toggle = this.toggle.bind(this);
|
||||
this.state = {
|
||||
activeTab: '1'
|
||||
};
|
||||
}
|
||||
|
||||
toggle(tab) {
|
||||
if (this.state.activeTab !== tab) {
|
||||
this.setState({
|
||||
activeTab: tab
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const urlParams = this.props.match.params;
|
||||
|
||||
return (
|
||||
<Container fluid={true} id="orders-container">
|
||||
<Row>
|
||||
<Col lg="12" md="12" sm="12" xs="12">
|
||||
{
|
||||
urlParams.idOrder ?
|
||||
<ProcessContainer idOrder={urlParams.idOrder}/> :
|
||||
<div id="orders-list-container">
|
||||
<Nav tabs>
|
||||
<NavItem>
|
||||
<NavLink id="activeOrders" className={classnames({active: this.state.activeTab === '1'}) + ' orders-tab'}
|
||||
onClick={() => { this.toggle('1'); }}>
|
||||
{orderTexts.labels.ACTIVE_ORDERS}
|
||||
</NavLink>
|
||||
</NavItem>
|
||||
<NavItem>
|
||||
<NavLink id="historyOrders" className={classnames({ active: this.state.activeTab === '2' }) + ' orders-tab'}
|
||||
onClick={() => { this.toggle('2'); }}>
|
||||
{orderTexts.labels.ORDER_HISTORY}
|
||||
</NavLink>
|
||||
</NavItem>
|
||||
</Nav>
|
||||
|
||||
<TabContent activeTab={this.state.activeTab}>
|
||||
<TabPane tabId="1">
|
||||
<Row>
|
||||
<Col lg="12" md="12" sm="12" xs="12">
|
||||
<OrdersDataContainer type="active" />
|
||||
</Col>
|
||||
</Row>
|
||||
</TabPane>
|
||||
<TabPane tabId="2">
|
||||
<Row>
|
||||
<Col lg="12" md="12" sm="12" xs="12">
|
||||
<OrdersDataContainer type="history" />
|
||||
</Col>
|
||||
</Row>
|
||||
</TabPane>
|
||||
</TabContent>
|
||||
</div>
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default OrdersContainer;
|
||||
57
frontend/src/containers/orders/OrdersDataContainer.jsx
Normal file
57
frontend/src/containers/orders/OrdersDataContainer.jsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import {Alert, Row, Col} from 'reactstrap';
|
||||
import WiaasBox from '../../mainComponents/box/WiaasBox.jsx';
|
||||
import {getActiveOrders, getHistoryOrders} from '../../actions/orders/ordersActions';
|
||||
import OrderList from './components/OrderList.jsx';
|
||||
import OrderListHeader from './components/OrderListHeader.jsx';
|
||||
import {orderTexts} from '../../constants/ordersConstants';
|
||||
|
||||
class OrdersDataContainer extends Component {
|
||||
componentDidMount() {
|
||||
this.props.dispatch(getActiveOrders());
|
||||
this.props.dispatch(getHistoryOrders());
|
||||
}
|
||||
|
||||
checkIfOrdersExistForUser(orders) {
|
||||
return orders.every((order) => {
|
||||
return 'isMyOrder' in order && !order.isMyOrder;
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const {activeOrders, historyOrders, type, isLoading} = this.props;
|
||||
const orders = type ? type === 'active' ? activeOrders : historyOrders : {};
|
||||
const mainTitleOrder = type.charAt(0).toUpperCase() + type.slice(1);
|
||||
|
||||
return (
|
||||
<Row>
|
||||
<Col lg="12" xs="12">
|
||||
<WiaasBox id={type + "-orders-container"} mainTitle={mainTitleOrder + " Orders"} customHeader={OrderListHeader} customHeaderParams={type}>
|
||||
{
|
||||
isLoading &&
|
||||
<div className="loader">
|
||||
<i className="fa fa-spinner fa-spin fa-3x" aria-hidden="true"></i>
|
||||
</div>
|
||||
}
|
||||
{ (orders && !isLoading) &&
|
||||
<OrderList orders={orders} type={type}/>
|
||||
}
|
||||
{
|
||||
((orders && orders.length === 0 && !isLoading) || (orders && this.checkIfOrdersExistForUser(orders))) &&
|
||||
<Alert color="info">{orderTexts.labels.NO_RECORDS}</Alert>
|
||||
}
|
||||
</WiaasBox>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
activeOrders: state.ordersReducer.activeOrders,
|
||||
historyOrders: state.ordersReducer.historyOrders,
|
||||
isLoading: state.ordersReducer.isLoading
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(OrdersDataContainer);
|
||||
267
frontend/src/containers/orders/ProcessContainer.jsx
Normal file
267
frontend/src/containers/orders/ProcessContainer.jsx
Normal file
@@ -0,0 +1,267 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import WiaasBox from '../../mainComponents/box/WiaasBox.jsx';
|
||||
import {fetchOrderInfo, getAllDataForInstallation} from '../../actions/orders/processActions';
|
||||
import OrderInfo from './components/OrderInfo.jsx';
|
||||
import OrderProcess from './components/process/OrderProcess.jsx';
|
||||
import ProcessPackage from './components/packages/ProcessPackage.jsx';
|
||||
import OrderComments from './components/OrderComments.jsx';
|
||||
import PackagesNav from './components/PackagesNav.jsx';
|
||||
import PriceHelper from '../../helpers/coMarket/PriceHelper';
|
||||
import ProcessNavContainer from './ProcessNavContainer.jsx';
|
||||
import OrderDocuments from './components/OrderDocuments.jsx';
|
||||
import {orderTexts} from '../../constants/ordersConstants';
|
||||
import './style/ProcessContainer.css';
|
||||
import './style/ProcessNavContainer.css';
|
||||
|
||||
const priceHelper = new PriceHelper();
|
||||
const usedForDirective = 'installationScheduling';
|
||||
const stepsNameForInstallation = {
|
||||
firstStepEnabled: 5,
|
||||
lastStepEnabled: 6
|
||||
};
|
||||
const fileType = 'installationProtocol';
|
||||
|
||||
class ProcessContainer extends Component {
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.onViewChange = this.onViewChange.bind(this);
|
||||
this.getActiveView = this.getActiveView.bind(this);
|
||||
this.onPackageFilter = this.onPackageFilter.bind(this);
|
||||
this.filterPackages = this.filterPackages.bind(this);
|
||||
this.state = {
|
||||
activeView : 'info',
|
||||
packageNameFilter: 'all',
|
||||
isSchedulingDisabled: {},
|
||||
isOnePackageAndInstallationNotExists: {},
|
||||
isInstallationInPackage: {},
|
||||
orderPackagePairs: [],
|
||||
tooltipOpen: false,
|
||||
isScheduleBtnClicked: false
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.dispatch(fetchOrderInfo(this.props.idOrder));
|
||||
this.props.dispatch(getAllDataForInstallation(this.props.idOrder, usedForDirective, stepsNameForInstallation, fileType));
|
||||
const orderPackagePairs = [];
|
||||
const isSchedulingDisabled = {};
|
||||
isSchedulingDisabled[this.props.idOrder] = true;
|
||||
const newState = Object.assign(isSchedulingDisabled, this.state.isSchedulingDisabled);
|
||||
|
||||
if(this.props.orderInfo) {
|
||||
this.props.orderInfo.packages.forEach(orderPackage => {
|
||||
orderPackagePairs.push(orderPackage.idOrder + '-' + orderPackage.idPackage);
|
||||
});
|
||||
}
|
||||
this.setState({
|
||||
orderPackagePairs,
|
||||
isSchedulingDisabled: newState
|
||||
});
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const {installCompanies, isComponentDisabled, earliestInstallDate, areAllShippingDatesConfirmed} = nextProps;
|
||||
const allPackagesScheduleInstallDisabled = [];
|
||||
const areComponentsDisabled = {};
|
||||
const isInstallationSet = {};
|
||||
const isOnePackageAndInstallationNotExists = {};
|
||||
const isInstallationInPackage = {};
|
||||
|
||||
if(installCompanies && isComponentDisabled && earliestInstallDate) {
|
||||
if(nextProps.orderInfo) {
|
||||
nextProps.orderInfo.packages.forEach(orderPackage => {
|
||||
const idOrder = orderPackage && orderPackage.idOrder;
|
||||
const idOrderPackagePair = orderPackage ? idOrder + '-' + orderPackage.idPackage : '';
|
||||
orderPackage.idOrderPackagePair = idOrderPackagePair;
|
||||
areComponentsDisabled[idOrder] = this.checkIfComponentIsDisabled(orderPackage.idOrder, isComponentDisabled, earliestInstallDate);
|
||||
|
||||
const availableCompanies = {};
|
||||
const selectedCompanies = {};
|
||||
isInstallationSet[idOrderPackagePair] = false;
|
||||
|
||||
if(installCompanies) {
|
||||
availableCompanies[idOrderPackagePair] = idOrderPackagePair in installCompanies.available ? installCompanies.available[idOrderPackagePair] : [];
|
||||
selectedCompanies[idOrderPackagePair] = idOrderPackagePair in installCompanies.selected ? installCompanies.selected[idOrderPackagePair] : {};
|
||||
if (idOrderPackagePair in selectedCompanies && Object.keys(selectedCompanies[idOrderPackagePair]).length > 0) {
|
||||
isInstallationSet[idOrderPackagePair] = true;
|
||||
}
|
||||
|
||||
if(availableCompanies[idOrderPackagePair].length === 0 && Object.keys(selectedCompanies[idOrderPackagePair]).length === 0) {
|
||||
isOnePackageAndInstallationNotExists[orderPackage.idOrder] = nextProps.orderInfo.packages.length === 1 ? true : false;
|
||||
isInstallationInPackage[idOrderPackagePair] = false;
|
||||
} else {
|
||||
isInstallationInPackage[idOrderPackagePair] = true;
|
||||
}
|
||||
}
|
||||
|
||||
const isSchedulingDisabled = areComponentsDisabled[idOrder] || (isInstallationSet && !isInstallationSet[idOrderPackagePair]);
|
||||
allPackagesScheduleInstallDisabled.push(isSchedulingDisabled);
|
||||
});
|
||||
|
||||
const isSchedulingDisabled = Object.assign({}, this.state.isSchedulingDisabled);
|
||||
isSchedulingDisabled[nextProps.orderInfo.info.id] = allPackagesScheduleInstallDisabled.every(isDisabled => {return isDisabled === true;});
|
||||
this.setState({
|
||||
isSchedulingDisabled,
|
||||
areComponentsDisabled,
|
||||
isInstallationSet,
|
||||
isOnePackageAndInstallationNotExists,
|
||||
isInstallationInPackage,
|
||||
areAllShippingDatesConfirmed,
|
||||
packages: nextProps.orderInfo.packages
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkIfComponentIsDisabled(idOrder, isComponentDisabled, earliestInstallDate) {
|
||||
if(isComponentDisabled && usedForDirective in isComponentDisabled && idOrder in isComponentDisabled[usedForDirective]) {
|
||||
const isScheduleComponentDisabled = isComponentDisabled[usedForDirective][idOrder];
|
||||
if(earliestInstallDate) {
|
||||
return isScheduleComponentDisabled || (!(idOrder in earliestInstallDate) || earliestInstallDate[idOrder] === '-');
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
calculatetTotalPrice(packages) {
|
||||
let fixedPrice = priceHelper.sumPrices(packages.map(pkg => { return pkg.units * pkg.packageFixedPrice}));
|
||||
let recurrentPrice = priceHelper.sumPrices(packages.map(pkg => { return pkg.units * pkg.packageRecuringPrice}));
|
||||
let servicesPrice = priceHelper.sumPrices(packages.map(pkg => { return pkg.units * pkg.packageServicePrice}));
|
||||
|
||||
return {
|
||||
fixedPrice,
|
||||
recurrentPrice: priceHelper.sumPrices([recurrentPrice, servicesPrice]),
|
||||
periodUnit: packages[0].periodUnit,
|
||||
currency: packages[0].packageCurrency.currency
|
||||
}
|
||||
}
|
||||
|
||||
onViewChange(activeView){
|
||||
if(activeView === 'documents'){
|
||||
this.props.dispatch(fetchOrderInfo(this.props.idOrder));
|
||||
}
|
||||
this.setState({activeView});
|
||||
}
|
||||
|
||||
getActiveView() {
|
||||
return this.state.activeView;
|
||||
}
|
||||
|
||||
onPackageFilter(packageNameFilter) {
|
||||
this.setState({packageNameFilter});
|
||||
}
|
||||
|
||||
filterPackages(orderPackage){
|
||||
if(this.state.packageNameFilter === 'all') {
|
||||
return true;
|
||||
}else{
|
||||
return orderPackage.packageName === this.state.packageNameFilter;
|
||||
}
|
||||
}
|
||||
|
||||
getProcess(process){
|
||||
const processKeys = Object.keys(process) || [];
|
||||
return processKeys.length > 0 ? process[processKeys[0]] : {};
|
||||
}
|
||||
|
||||
getButtonClass() {
|
||||
if(this.props.orderInfo) {
|
||||
return this.state.isSchedulingDisabled[this.props.orderInfo.id] ? 'schedule-inactive' : 'schedule-active';
|
||||
}
|
||||
|
||||
return 'schedule-inactive';
|
||||
}
|
||||
|
||||
render() {
|
||||
const {orderInfo, isLoading} = this.props;
|
||||
|
||||
return (
|
||||
<div id="order-info">
|
||||
{
|
||||
isLoading &&
|
||||
<div className="loader">
|
||||
<i className="fa fa-spinner fa-spin fa-3x" aria-hidden="true"></i>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
(orderInfo && orderInfo.info && !isLoading) &&
|
||||
<div>
|
||||
<WiaasBox
|
||||
customHeader={ProcessNavContainer}
|
||||
customHeaderParams={{
|
||||
orderInfo: orderInfo.info,
|
||||
packages: orderInfo.packages,
|
||||
onViewChange: this.onViewChange,
|
||||
getActiveView: this.getActiveView,
|
||||
installationData: this.state
|
||||
}}>
|
||||
<OrderInfo totalPrice={this.calculatetTotalPrice(orderInfo.packages)} orderDetails={orderInfo} installationData={this.state}/>
|
||||
</WiaasBox>
|
||||
{
|
||||
this.state.activeView !== 'info' &&
|
||||
<div className="components-link">
|
||||
<div className="link-line"></div>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
this.state.activeView === 'info' &&
|
||||
<OrderProcess
|
||||
onViewChange={this.onViewChange}
|
||||
orderStatus={orderInfo.status}
|
||||
orderProcess={this.getProcess(orderInfo.process)}/>
|
||||
}
|
||||
{
|
||||
this.state.activeView === 'packages' &&
|
||||
<WiaasBox id="order-packages"
|
||||
customHeader={PackagesNav}
|
||||
customHeaderParams={{packages: orderInfo.packages, onPackageFilter: this.onPackageFilter, packageNameFilter: this.state.packageNameFilter}}
|
||||
>
|
||||
{
|
||||
orderInfo.packages.filter(this.filterPackages).map(orderPackage =>
|
||||
<ProcessPackage key={orderPackage.idPackage}
|
||||
onViewChange={this.onViewChange}
|
||||
idCommercialLead={orderInfo.info.idCommercialLead}
|
||||
orderPackage={orderPackage}/>
|
||||
)
|
||||
}
|
||||
</WiaasBox>
|
||||
}
|
||||
{
|
||||
this.state.activeView === 'comments' &&
|
||||
<OrderComments orderInfo={orderInfo.info} orderComments={orderInfo.orderComments} orderPackages={orderInfo.packages}/>
|
||||
}
|
||||
|
||||
{
|
||||
this.state.activeView === 'documents' &&
|
||||
<OrderDocuments idOrder={orderInfo.info.id} />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
(orderInfo && !orderInfo.info && !isLoading) &&
|
||||
<div className="no-rigths">
|
||||
{orderTexts.labels.NOT_AVAILABLE}!
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
isCompanyAdmin: state.auth.isCompanyAdmin,
|
||||
orderInfo: state.processReducer.orderInfo,
|
||||
confirmationDates: state.processReducer.confirmationDates,
|
||||
isLoading: state.processReducer.isLoading,
|
||||
isNextStepWanted: state.processReducer.isNextStepWanted,
|
||||
isComponentDisabled: state.processReducer.isComponentDisabled,
|
||||
earliestInstallDate: state.processReducer.earliestInstallDate,
|
||||
installCompanies: state.processReducer.installCompanies,
|
||||
areAllShippingDatesConfirmed: state.processReducer.areAllShippingDatesConfirmed
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(ProcessContainer);
|
||||
110
frontend/src/containers/orders/ProcessNavContainer.jsx
Normal file
110
frontend/src/containers/orders/ProcessNavContainer.jsx
Normal file
@@ -0,0 +1,110 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import {Row, Col, Button, Tooltip} from 'reactstrap';
|
||||
import {orderTexts} from '../../constants/ordersConstants';
|
||||
import {setDialogContent, setDialogOpenFlag} from '../../actions/dialog/dialogActions';
|
||||
import InstallationSchedulingContainer from './InstallationSchedulingContainer.jsx';
|
||||
|
||||
class ProcessNavContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
tooltipOpen: false,
|
||||
isScheduleBtnClicked: false
|
||||
};
|
||||
|
||||
this.toggle = this.toggle.bind(this);
|
||||
this.handleScheduleBtn = this.handleScheduleBtn.bind(this);
|
||||
this.setContentDialog = this.setContentDialog.bind(this);
|
||||
this.openDialogContent = this.openDialogContent.bind(this);
|
||||
}
|
||||
|
||||
getClass(buttonView) {
|
||||
const view = this.props.params.getActiveView();
|
||||
|
||||
return buttonView === view ? 'process-nav-div selected-nav' : 'process-nav-div';
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.setState({
|
||||
tooltipOpen: !this.state.tooltipOpen
|
||||
});
|
||||
}
|
||||
|
||||
handleScheduleBtn() {
|
||||
this.setState({isScheduleBtnClicked: !this.state.isScheduleBtnClicked});
|
||||
}
|
||||
|
||||
setContentDialog() {
|
||||
const {installationData} = this.props.params;
|
||||
|
||||
return {
|
||||
class: 'installation-scheduling',
|
||||
hasCloseIcon: true,
|
||||
header: orderTexts.labels.INSTALLATION_SCHEDULE_HEADER,
|
||||
TagName: InstallationSchedulingContainer,
|
||||
params: {
|
||||
orderPackages: installationData.packages,
|
||||
areComponentsDisabled: installationData.areComponentsDisabled,
|
||||
isInstallationSet: installationData.isInstallationSet,
|
||||
isInstallationInPackage: installationData.isInstallationInPackage,
|
||||
areAllShippingDatesConfirmed: installationData.areAllShippingDatesConfirmed,
|
||||
openDialogContent: this.openDialogContent
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
openDialogContent() {
|
||||
if(!this.props.params.installationData.isSchedulingDisabled[this.props.params.orderInfo.id]) {
|
||||
const dialogContent = this.setContentDialog();
|
||||
|
||||
this.props.dispatch(setDialogOpenFlag(true));
|
||||
this.props.dispatch(setDialogContent(dialogContent));
|
||||
}
|
||||
}
|
||||
|
||||
getButtonClass() {
|
||||
const {installationData, orderInfo} = this.props.params;
|
||||
|
||||
return installationData.isSchedulingDisabled[orderInfo.id] ? 'schedule-inactive' : 'schedule-active';
|
||||
}
|
||||
|
||||
render() {
|
||||
const {orderInfo, onViewChange, installationData} = this.props.params;
|
||||
|
||||
return (
|
||||
<Row id="process-nav" className="process-nav">
|
||||
<Col xl="2" lg="2" md="4" sm="12" xs="12" className="process-nav-buttons">
|
||||
<div className="wiaas-main-title">
|
||||
{orderTexts.labels.ORDER} {orderInfo.orderNumber} <div className={'status-layer ' + orderInfo.status}>{orderTexts.statuses[orderInfo.status]}</div>
|
||||
</div>
|
||||
</Col>
|
||||
<Col xl="2" lg="2" md="2" sm="12" xs="12" className="process-nav-buttons">
|
||||
<Button className={"schedule-installation-btn " + this.getButtonClass()}
|
||||
id="schedule-installation-button"
|
||||
onClick={this.openDialogContent}>
|
||||
{orderTexts.buttons.SCHEDULE_INSTALLATION}
|
||||
</Button>
|
||||
<Tooltip placement="bottom" isOpen={this.state.tooltipOpen} target="schedule-installation-button" toggle={this.toggle}>
|
||||
{
|
||||
installationData.isSchedulingDisabled[orderInfo.id]
|
||||
? installationData.isOnePackageAndInstallationNotExists[orderInfo.id]
|
||||
? orderTexts.labels.SCHEDULE_INSTALLATION_NOT_EXIST
|
||||
: orderTexts.labels.SCHEDULE_INSTALLATION_DISABLED
|
||||
: orderTexts.labels.SCHEDULE_INSTALLATION_ENABLED
|
||||
}
|
||||
</Tooltip>
|
||||
</Col>
|
||||
<Col xl="4" lg="6" md="6" sm="12" xs="12" className="process-menu">
|
||||
<div className={this.getClass('info')} onClick={()=>{onViewChange('info')}}>{orderTexts.labels.ORDER_INFO}</div>
|
||||
<div className={this.getClass('packages')} onClick={()=>{onViewChange('packages')}}>{orderTexts.labels.PACKAGES}</div>
|
||||
<div className={this.getClass('comments')} onClick={()=>{onViewChange('comments')}}>{orderTexts.labels.COMMENTS}</div>
|
||||
<div className={this.getClass('documents')} onClick={()=>{onViewChange('documents')}}>{orderTexts.labels.DOCUMENTS}</div>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default connect()(ProcessNavContainer);
|
||||
@@ -0,0 +1,79 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import {Button} from 'reactstrap';
|
||||
import {Link} from 'react-router-dom';
|
||||
import {WiaasTableRow, WiaasTableCol} from '../../../mainComponents/table/WiaasTable.jsx';
|
||||
import {orderTexts} from '../../../constants/ordersConstants';
|
||||
import '../style/Orders.css';
|
||||
import OrderPackage from './OrderPackage.jsx';
|
||||
|
||||
class ActiveOrderItem extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
showPackages: false
|
||||
};
|
||||
|
||||
this.toggle = this.toggle.bind(this);
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.setState({
|
||||
showPackages: !this.state.showPackages
|
||||
});
|
||||
}
|
||||
|
||||
getIconClass(type) {
|
||||
return 'fa fa-angle-' + type + ' toggle-view-packages';
|
||||
}
|
||||
|
||||
render() {
|
||||
const {order, isViewAllOrdersChecked} = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<WiaasTableRow className={"order-central-row order-border-" + order.status}>
|
||||
<WiaasTableCol header="#">
|
||||
{!this.state.showPackages && <i className={this.getIconClass('down')} aria-hidden="true" onClick={this.toggle}></i>}
|
||||
{this.state.showPackages && <i className={this.getIconClass('up')} aria-hidden="true" onClick={this.toggle}></i>}
|
||||
<i className="fa fa-list-alt package-photo" aria-hidden="true" />
|
||||
<div className="order-number">{order.orderNumber}</div>
|
||||
</WiaasTableCol>
|
||||
<WiaasTableCol header={orderTexts.labels.REFERENCE}>{order.reference ? order.reference : '-'}</WiaasTableCol>
|
||||
{isViewAllOrdersChecked['active'] && <WiaasTableCol header={orderTexts.labels.PLACED_BY}>{order.customerName ? order.customerName : ''}</WiaasTableCol>}
|
||||
<WiaasTableCol header={orderTexts.labels.ORDER_DATE}>{order.orderDate ? order.orderDate : '-'}</WiaasTableCol>
|
||||
<WiaasTableCol header={orderTexts.labels.EST_DELIVERY}>{order.estimatedDeliveryDate ? order.estimatedDeliveryDate : '-'}</WiaasTableCol>
|
||||
<WiaasTableCol header="Catalogue">
|
||||
<div className="order-item-cl">
|
||||
<img className="cl-photo" src="static/img/man-icon.png" alt="Catalogue" />
|
||||
<div className="cl-details">
|
||||
<div className="cl-contact-name">{order.clContactName}</div>
|
||||
<div className="cl-name">{order.clName}</div>
|
||||
</div>
|
||||
</div>
|
||||
</WiaasTableCol>
|
||||
<WiaasTableCol header={orderTexts.labels.AMOUNT}>
|
||||
{order.orderCurrency && order.orderCurrency.currency
|
||||
? order.orderTotalPrice.toLocaleString() + ' ' + order.orderCurrency.currency
|
||||
: parseFloat(order.orderTotalPrice).toLocaleString()}
|
||||
</WiaasTableCol>
|
||||
<WiaasTableCol header={orderTexts.labels.STATUS}>
|
||||
<div className={'status-icon ' + order.status}></div>{order.status}
|
||||
</WiaasTableCol>
|
||||
<WiaasTableCol header="Buttons details">
|
||||
<Link to={'/orders/' + order.id} className="actions-link">
|
||||
<Button color="secondary" className="actions-button">{orderTexts.buttons.DELIVERY_DETAILS}</Button>
|
||||
</Link>
|
||||
|
||||
</WiaasTableCol>
|
||||
</WiaasTableRow>
|
||||
{ this.state.showPackages && <OrderPackage order={order} type="active"/> }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
isViewAllOrdersChecked: state.ordersReducer.isViewAllOrdersChecked
|
||||
});
|
||||
export default connect(mapStateToProps)(ActiveOrderItem);
|
||||
26
frontend/src/containers/orders/components/AddComment.jsx
Normal file
26
frontend/src/containers/orders/components/AddComment.jsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import React, {Component} from 'react';
|
||||
import { Editor } from '@tinymce/tinymce-react';
|
||||
|
||||
class AddComment extends Component {
|
||||
handleEditorChange = (e) => {
|
||||
const comment = e.target.getContent();
|
||||
this.props.onEditorChange(comment);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Editor
|
||||
init={{
|
||||
plugins: 'link textcolor lists colorpicker code',
|
||||
toolbar: 'undo redo | styleselect | bold italic underline forecolor fontsizeselect | link | alignleft aligncenter alignright | numlist bullist | outdent indent | code'
|
||||
}}
|
||||
onChange={this.handleEditorChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AddComment;
|
||||
@@ -0,0 +1,81 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import {Dropdown, DropdownToggle, DropdownMenu, DropdownItem} from 'reactstrap';
|
||||
import {Link} from 'react-router-dom';
|
||||
import SupportMail from './SupportMail.jsx';
|
||||
import {setDialogContent, setDialogOpenFlag} from '../../../actions/dialog/dialogActions';
|
||||
import {sendSupportMail} from '../../../actions/orders/processActions';
|
||||
import {orderTexts} from '../../../constants/ordersConstants';
|
||||
|
||||
class HistoryOrdersButtons extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.toggle = this.toggle.bind(this);
|
||||
this.sendSupportMail = this.sendSupportMail.bind(this);
|
||||
this.openDialogContent = this.openDialogContent.bind(this);
|
||||
|
||||
this.state = {
|
||||
dropdownOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.setState({
|
||||
dropdownOpen: !this.state.dropdownOpen
|
||||
});
|
||||
}
|
||||
|
||||
openDialogContent() {
|
||||
const dialogContent = {
|
||||
buttons: [
|
||||
{
|
||||
color: 'secondary',
|
||||
name: orderTexts.buttons.SEND,
|
||||
id: 'send-mail-to-support-btn',
|
||||
action: this.sendSupportMail
|
||||
},
|
||||
{
|
||||
color: 'secondary',
|
||||
name: orderTexts.buttons.CANCEL,
|
||||
id: 'cancel-send-mail-to-support-btn'
|
||||
}
|
||||
],
|
||||
header: orderTexts.labels.SUPPORT_MESSAGE_HEADER,
|
||||
TagName: SupportMail,
|
||||
params: {orderInfo: this.props.order, orderPackages: this.props.order.packages}
|
||||
};
|
||||
|
||||
this.props.dispatch(setDialogOpenFlag(true));
|
||||
this.props.dispatch(setDialogContent(dialogContent));
|
||||
}
|
||||
|
||||
sendSupportMail() {
|
||||
this.props.dispatch(sendSupportMail(this.props.order, this.props.order.packages, this.props.supportText));
|
||||
}
|
||||
|
||||
render() {
|
||||
const {order} = this.props;
|
||||
|
||||
return (
|
||||
<Dropdown size="sm" isOpen={this.state.dropdownOpen} toggle={this.toggle}>
|
||||
<DropdownToggle className="actions-button" caret>
|
||||
{orderTexts.buttons.ACTIONS}
|
||||
</DropdownToggle>
|
||||
<DropdownMenu right>
|
||||
<DropdownItem className="actions-item" onClick={this.openDialogContent}> {orderTexts.buttons.SUPPORT}
|
||||
</DropdownItem>
|
||||
<Link to={'/orders/' + order.id} className="actions-link">
|
||||
<DropdownItem className="actions-item">
|
||||
{orderTexts.buttons.DETAILS}
|
||||
</DropdownItem>
|
||||
</Link>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
supportText: state.processReducer.supportText
|
||||
});
|
||||
export default connect(mapStateToProps)(HistoryOrdersButtons);
|
||||
@@ -0,0 +1,77 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import {WiaasTableRow, WiaasTableCol} from '../../../mainComponents/table/WiaasTable.jsx';
|
||||
import {orderTexts} from '../../../constants/ordersConstants';
|
||||
import '../style/Orders.css';
|
||||
import OrderPackage from './OrderPackage.jsx';
|
||||
import HistoryOrderButtons from './HistoryOrderButtons.jsx';
|
||||
|
||||
class HistoryOrdersItem extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
showPackages: false
|
||||
};
|
||||
|
||||
this.toggle = this.toggle.bind(this);
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.setState({
|
||||
showPackages: !this.state.showPackages
|
||||
});
|
||||
}
|
||||
|
||||
getIconClass(type) {
|
||||
return 'fa fa-angle-' + type + ' toggle-view-packages';
|
||||
}
|
||||
|
||||
render() {
|
||||
const {order, isViewAllOrdersChecked} = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<WiaasTableRow className={"order-central-row order-border-" + order.status}>
|
||||
<WiaasTableCol header="#">
|
||||
{!this.state.showPackages && <i className={this.getIconClass('down')} aria-hidden="true" onClick={this.toggle}></i>}
|
||||
{this.state.showPackages && <i className={this.getIconClass('up')} aria-hidden="true" onClick={this.toggle}></i>}
|
||||
<i className="fa fa-list-alt package-photo" aria-hidden="true" />
|
||||
<div className="order-number">{order.orderNumber}</div>
|
||||
</WiaasTableCol>
|
||||
<WiaasTableCol header={orderTexts.labels.REFERENCE}>{order.reference ? order.reference : '-'}</WiaasTableCol>
|
||||
{isViewAllOrdersChecked['history'] && <WiaasTableCol header={orderTexts.labels.PLACED_BY}>{order.customerName ? order.customerName : ''}</WiaasTableCol>}
|
||||
<WiaasTableCol header={orderTexts.labels.ORDER_DATE}>{order.orderDate ? order.orderDate : '-'}</WiaasTableCol>
|
||||
<WiaasTableCol header={orderTexts.labels.DELIVERY_DATE}>{order.deliveryDate}</WiaasTableCol>
|
||||
<WiaasTableCol header="Catalogue">
|
||||
<div className="order-item-cl">
|
||||
<img className="cl-photo" src="static/img/man-icon.png" alt="Catalogue" />
|
||||
<div className="cl-details">
|
||||
<div className="cl-contact-name">{order.clContactName}</div>
|
||||
<div className="cl-name">{order.clName}</div>
|
||||
</div>
|
||||
</div>
|
||||
</WiaasTableCol>
|
||||
<WiaasTableCol header={orderTexts.labels.AMOUNT}>
|
||||
{order.orderCurrency && order.orderCurrency.currency
|
||||
? order.orderTotalPrice.toLocaleString() + ' ' + order.orderCurrency.currency
|
||||
: parseFloat(order.orderTotalPrice).toLocaleString()}
|
||||
</WiaasTableCol>
|
||||
<WiaasTableCol header={orderTexts.labels.STATUS}>
|
||||
<div className={'status-icon ' + order.status}></div>{orderTexts.statuses[order.status]}
|
||||
</WiaasTableCol>
|
||||
<WiaasTableCol header="End of life">{order.endOfLife}</WiaasTableCol>
|
||||
<WiaasTableCol header="Buttons details">
|
||||
<HistoryOrderButtons order={order}/>
|
||||
</WiaasTableCol>
|
||||
</WiaasTableRow>
|
||||
{ this.state.showPackages && <OrderPackage order={order} type="history"/> }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
isViewAllOrdersChecked: state.ordersReducer.isViewAllOrdersChecked
|
||||
});
|
||||
export default connect(mapStateToProps)(HistoryOrdersItem);
|
||||
72
frontend/src/containers/orders/components/OrderComments.jsx
Normal file
72
frontend/src/containers/orders/components/OrderComments.jsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import {Button, Container, Row, Col} from 'reactstrap';
|
||||
import WiaasBox from '../../../mainComponents/box/WiaasBox.jsx';
|
||||
import AddComment from './AddComment.jsx';
|
||||
import {addComment} from '../../../actions/orders/processActions';
|
||||
import {orderTexts} from '../../../constants/ordersConstants';
|
||||
|
||||
class OrderComments extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onEditorChange = this.onEditorChange.bind(this);
|
||||
this.addNewComment = this.addNewComment.bind(this);
|
||||
this.state = {
|
||||
newComment: ''
|
||||
};
|
||||
}
|
||||
|
||||
addNewComment(){
|
||||
this.props.dispatch(addComment(this.props.orderInfo.id, this.state.newComment));
|
||||
}
|
||||
|
||||
onEditorChange(newComment){
|
||||
this.setState({newComment});
|
||||
}
|
||||
|
||||
getOffset(isOwner){
|
||||
return isOwner ? 6 : 0;
|
||||
}
|
||||
|
||||
getClassByOwner(isOwner){
|
||||
return isOwner ? 'mine' : '';
|
||||
}
|
||||
|
||||
render() {
|
||||
const {orderComments} = this.props;
|
||||
|
||||
return (
|
||||
<div id="order-comments" className="order-comments">
|
||||
<WiaasBox mainTitle="Comments">
|
||||
<Container fluid={true} className="order-coments-body">
|
||||
<Row>
|
||||
<Col xl="6">
|
||||
{
|
||||
orderComments &&
|
||||
orderComments.map((orderComment, index) =>
|
||||
<Row key={'order-comment-' + index}>
|
||||
<Col xl={{size:6, offset:this.getOffset(orderComment.isOwner)}}>
|
||||
<div className={'order-comment ' + this.getClassByOwner(orderComment.isOwner)} key={'order-comment-' + index}>
|
||||
<div className="order-comment-header">{orderComment.username} - {orderComment.addDate}</div>
|
||||
<div dangerouslySetInnerHTML={{__html: orderComment.comment}}></div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
)
|
||||
}
|
||||
</Col>
|
||||
<Col xl="6">
|
||||
<AddComment onEditorChange={this.onEditorChange}/>
|
||||
<Button onClick={()=>{this.addNewComment()}} className="new-comment-button" color="secondary">{orderTexts.buttons.ADD_COMMENT}</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
</WiaasBox>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default connect()(OrderComments);
|
||||
26
frontend/src/containers/orders/components/OrderDocuments.jsx
Normal file
26
frontend/src/containers/orders/components/OrderDocuments.jsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import OrderDocumentsGroup from './OrderDocumentsGroup.jsx';
|
||||
import {orderTexts} from '../../../constants/ordersConstants';
|
||||
|
||||
class OrderDocuments extends Component {
|
||||
render() {
|
||||
const {orderInfo} = this.props;
|
||||
|
||||
return (
|
||||
<div id="order-documents" className="order-documents">
|
||||
{
|
||||
orderInfo.packages.map(orderPackage => <OrderDocumentsGroup key={'order-package-' + orderPackage.idPackage} documentsGroup={orderPackage} />)
|
||||
}
|
||||
{
|
||||
orderInfo.orderDocuments && <OrderDocumentsGroup key={'order-package-0'} documentsGroup={{documents: orderInfo.orderDocuments, packageName: orderTexts.labels.OTHER_DOCS}} />
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
orderInfo: state.processReducer.orderInfo
|
||||
});
|
||||
export default connect(mapStateToProps)(OrderDocuments);
|
||||
@@ -0,0 +1,85 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Tooltip} from 'reactstrap';
|
||||
import WiaasBox from '../../../mainComponents/box/WiaasBox.jsx';
|
||||
import {API_SERVER} from '../../../config';
|
||||
import FileDownloader from '../../../helpers/FileDownloader';
|
||||
|
||||
const fileHandler = new FileDownloader();
|
||||
|
||||
const iconTypes = {
|
||||
doc: 'file-word-o',
|
||||
docx: 'file-word-o',
|
||||
odt: 'file-word-o',
|
||||
ods: 'file-excel-o',
|
||||
pdf: 'file-pdf-o',
|
||||
png: 'file-image-o',
|
||||
jpg: 'file-image-o',
|
||||
xls: 'file-excel-o',
|
||||
xlsx: 'file-excel-o',
|
||||
ppt: 'file-powerpoint-o',
|
||||
pptx: 'file-powerpoint-o'
|
||||
}
|
||||
|
||||
class OrderDocumentsGroup extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.toggle = this.toggle.bind(this);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
toggle(idDocument) {
|
||||
const obj = {}
|
||||
obj[idDocument] = !this.state[idDocument];
|
||||
|
||||
this.setState(obj);
|
||||
}
|
||||
|
||||
getDocumentIcon(documentType) {
|
||||
return iconTypes[documentType] || 'file';
|
||||
}
|
||||
|
||||
getDocumentText(document) {
|
||||
const name = document.documentName + '.' + document.extension;
|
||||
|
||||
return name.length > 9 ? name.substring(0, 10) + '...' : name;
|
||||
}
|
||||
|
||||
downloadDocument(document){
|
||||
const fileUrl = `${API_SERVER}/utils/api/downloadFile?idDocument=${document.idDocument}&fileName=${document.documentName}.${document.extension}&fileType=${document.documentTypeName}`
|
||||
const fileName = document.documentName + '.' + document.extension;
|
||||
fileHandler.download(fileUrl, fileName);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {documentsGroup} = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
documentsGroup.documents.length > 0 &&
|
||||
<WiaasBox mainTitle={documentsGroup.packageName}>
|
||||
{
|
||||
documentsGroup.documents.map(document => <a id={'document-' + document.idDocument} key={'order-document-' + document.idDocument}>
|
||||
<div onClick={() => {this.downloadDocument(document)}} className="document-link-big">
|
||||
<i className={'fa fa-4x fa-' + this.getDocumentIcon(document.extension)} aria-hidden="true"></i>
|
||||
<div>
|
||||
{this.getDocumentText(document)}
|
||||
<Tooltip placement="bottom"
|
||||
delay={{ show: 0, hide: 0}}
|
||||
container="order-documents"
|
||||
isOpen={this.state[document.idDocument]}
|
||||
target={'document-' + document.idDocument}
|
||||
toggle={()=>this.toggle(document.idDocument)}>
|
||||
{document.documentName} ({document.extension})
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div></a>)
|
||||
}
|
||||
</WiaasBox>
|
||||
}
|
||||
</div>)
|
||||
}
|
||||
}
|
||||
|
||||
export default OrderDocumentsGroup;
|
||||
152
frontend/src/containers/orders/components/OrderInfo.jsx
Normal file
152
frontend/src/containers/orders/components/OrderInfo.jsx
Normal file
@@ -0,0 +1,152 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import moment from 'moment';
|
||||
import {Container, Row, Col} from 'reactstrap';
|
||||
import TermsContainer from '../../terms/TermsContainer.jsx';
|
||||
import {orderTexts} from '../../../constants/ordersConstants';
|
||||
|
||||
class OrderInfo extends Component {
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
acceptedDate: {},
|
||||
proposedDate: {},
|
||||
isPreliminaryInstallationDate: true
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setInstallationData(this.props);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.setInstallationData(nextProps);
|
||||
}
|
||||
|
||||
setInstallationData(props) {
|
||||
const acceptedDate = {};
|
||||
const proposedDate = {};
|
||||
const idOrder = props.orderDetails.info.id;
|
||||
const {isInstallationInPackage} = props.installationData;
|
||||
const {confirmationDates, areAllShippingDatesConfirmed} = props;
|
||||
const isPreliminaryInstallationDate = areAllShippingDatesConfirmed && idOrder in areAllShippingDatesConfirmed ? !areAllShippingDatesConfirmed[idOrder] : true;
|
||||
const isInstallationInOrder = Object.keys(isInstallationInPackage).some(idOrderPackage => {return isInstallationInPackage[idOrderPackage] === true;});
|
||||
|
||||
props.orderDetails.packages.forEach(orderPackage => {
|
||||
const idOrderPackagePair = idOrder + '-' + orderPackage.idPackage;
|
||||
|
||||
if(confirmationDates && confirmationDates[idOrderPackagePair]) {
|
||||
const packageDates = confirmationDates[idOrderPackagePair];
|
||||
const accepted = Object.keys(packageDates).find(installDate => {return packageDates[installDate].lastStatus === 'accepted'});
|
||||
acceptedDate[idOrderPackagePair] = accepted ? moment(accepted).format('Do MMM, YYYY') : '';
|
||||
const proposed = Object.keys(packageDates).find(installDate => {return packageDates[installDate].lastStatus === 'proposed'});
|
||||
proposedDate[idOrderPackagePair] = proposed ? moment(proposed).format('Do MMM, YYYY') : '';
|
||||
}
|
||||
});
|
||||
|
||||
this.setState({acceptedDate, proposedDate, isPreliminaryInstallationDate, isInstallationInOrder});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {totalPrice, installationData} = this.props;
|
||||
const {acceptedDate, proposedDate, isPreliminaryInstallationDate, isInstallationInOrder} = this.state;
|
||||
const orderPackages = installationData.packages;
|
||||
const isInstallationInPackage = installationData.isInstallationInPackage;
|
||||
const orderInfo = this.props.orderInfo.info;
|
||||
|
||||
return (
|
||||
<Container fluid={true} id="order-info-description">
|
||||
<Row>
|
||||
<Col xl="2">
|
||||
<div className="subtitle"><h6>{orderTexts.labels.ORDER_DATE}:</h6></div>
|
||||
<span>{orderInfo.orderDate}</span>
|
||||
<div className="subtitle"><h6>{orderTexts.labels.SOLD_BY}:</h6></div>
|
||||
<span>{orderInfo.commercialLead}</span>
|
||||
|
||||
</Col>
|
||||
<Col xl="2">
|
||||
<div>
|
||||
<div className="subtitle"><h6>{orderTexts.labels.REFERENCE}:</h6></div>
|
||||
<span>{orderInfo.reference || '-'}</span>
|
||||
</div>
|
||||
<div>
|
||||
<div className="subtitle"><h6>{orderTexts.labels.BID}:</h6></div>
|
||||
<span>{orderInfo.tender || '-'}</span>
|
||||
</div>
|
||||
</Col>
|
||||
{ isInstallationInOrder &&
|
||||
<Col xl="3">
|
||||
<div>
|
||||
<div className="subtitle">
|
||||
{ isPreliminaryInstallationDate
|
||||
? <h6>{orderTexts.labels.PRELIMINARY_INSTALLATION_DATE_LABEL}:</h6>
|
||||
: <h6>{orderTexts.labels.INSTALLATION_DATE}:</h6>
|
||||
}
|
||||
</div>
|
||||
{ orderPackages &&
|
||||
orderPackages.map(orderPackage =>
|
||||
<div key={'package-install-date-' + orderPackage.idOrderPackagePair}>
|
||||
{ isInstallationInPackage[orderPackage.idOrderPackagePair] &&
|
||||
<div>
|
||||
{ orderPackages.length > 1 &&
|
||||
<span>{orderPackage.packageName}: </span>
|
||||
}
|
||||
<span className="installation-date-per-package">
|
||||
{ acceptedDate && acceptedDate[orderPackage.idOrderPackagePair]
|
||||
? acceptedDate[orderPackage.idOrderPackagePair]
|
||||
: proposedDate && proposedDate[orderPackage.idOrderPackagePair]
|
||||
? proposedDate[orderPackage.idOrderPackagePair]
|
||||
: orderTexts.labels.NOT_SET
|
||||
}
|
||||
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</Col>
|
||||
}
|
||||
|
||||
<Col xl="2">
|
||||
<div className="subtitle"><h6>{orderTexts.labels.TOTAL_DELVIERY_PRICE}:</h6></div>
|
||||
<span>{totalPrice.fixedPrice.toLocaleString()} {totalPrice.currency}</span>
|
||||
|
||||
{
|
||||
totalPrice.recurrentPrice > 0 &&
|
||||
<div>
|
||||
<div className="subtitle"><h6>{orderTexts.labels.TOTAL_RECURRENT_PRICE}:</h6></div>
|
||||
<span>
|
||||
{totalPrice.recurrentPrice.toLocaleString() + ' ' + totalPrice.currency}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
</Col>
|
||||
<Col xl="2">
|
||||
<div>
|
||||
<div className="subtitle"><h6>{orderTexts.labels.PROJECT}:</h6></div>
|
||||
<span>{orderInfo.projectName || '-'}</span>
|
||||
</div>
|
||||
|
||||
<div className="terms-link">
|
||||
<i className="fa fa-link"></i>
|
||||
<span className="terms-label">
|
||||
<TermsContainer idTerms={orderInfo.idTerms}/>
|
||||
</span>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
orderInfo: state.processReducer.orderInfo,
|
||||
confirmationDates: state.processReducer.confirmationDates,
|
||||
areAllShippingDatesConfirmed: state.processReducer.areAllShippingDatesConfirmed
|
||||
});
|
||||
export default connect(mapStateToProps)(OrderInfo);
|
||||
75
frontend/src/containers/orders/components/OrderList.jsx
Normal file
75
frontend/src/containers/orders/components/OrderList.jsx
Normal file
@@ -0,0 +1,75 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import ActiveOrderItem from './ActiveOrderItem.jsx';
|
||||
import HistoryOrderItem from './HistoryOrderItem.jsx';
|
||||
import {WiaasTable, WiaasTableHeader, WiaasTableBody} from '../../../mainComponents/table/WiaasTable.jsx';
|
||||
import {orderTexts} from '../../../constants/ordersConstants';
|
||||
|
||||
class OrderList extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.getHeadersByType = this.getHeadersByType.bind(this);
|
||||
}
|
||||
|
||||
getHeadersByType(type) {
|
||||
const activeOrdersHeader = [
|
||||
orderTexts.headers.ORDER,
|
||||
orderTexts.headers.REFERENCE,
|
||||
orderTexts.headers.ORDER_DATE,
|
||||
orderTexts.headers.ESTIMATED_DATE,
|
||||
orderTexts.headers.COMMERCIAL_LEAD,
|
||||
orderTexts.headers.AMOUNT,
|
||||
orderTexts.headers.STATUS,
|
||||
''
|
||||
];
|
||||
|
||||
const historyOrdersHeader = [
|
||||
orderTexts.headers.ORDER,
|
||||
orderTexts.headers.REFERENCE,
|
||||
orderTexts.headers.ORDER_DATE,
|
||||
orderTexts.headers.DELIVERY_DATE,
|
||||
orderTexts.headers.COMMERCIAL_LEAD,
|
||||
orderTexts.headers.AMOUNT,
|
||||
orderTexts.headers.STATUS,
|
||||
orderTexts.headers.END_OF_LIFE,
|
||||
''
|
||||
];
|
||||
|
||||
if(this.props.isCompanyAdmin && this.props.isViewAllOrdersChecked[type]) {
|
||||
activeOrdersHeader.splice(2, 0, orderTexts.headers.PLACED_BY);
|
||||
activeOrdersHeader.join();
|
||||
historyOrdersHeader.splice(2, 0, orderTexts.headers.PLACED_BY);
|
||||
historyOrdersHeader.join();
|
||||
}
|
||||
|
||||
return type === 'active' ? activeOrdersHeader : historyOrdersHeader;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {orders, type, isCompanyAdmin, isViewAllOrdersChecked} = this.props;
|
||||
const TagName = type && type === 'active' ? ActiveOrderItem : HistoryOrderItem;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<WiaasTable>
|
||||
<WiaasTableHeader headers={this.getHeadersByType(type)}/>
|
||||
<WiaasTableBody>
|
||||
{
|
||||
orders &&
|
||||
orders.map((order, index) =>
|
||||
(('isMyOrder' in order && order.isMyOrder) || (isCompanyAdmin && isViewAllOrdersChecked[type])) &&
|
||||
<TagName key={order.orderNumber} order={order} />
|
||||
)
|
||||
}
|
||||
</WiaasTableBody>
|
||||
</WiaasTable>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
isCompanyAdmin: state.auth.isCompanyAdmin,
|
||||
isViewAllOrdersChecked: state.ordersReducer.isViewAllOrdersChecked
|
||||
});
|
||||
export default connect(mapStateToProps)(OrderList);
|
||||
@@ -0,0 +1,56 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import {Row, Col, Input} from 'reactstrap';
|
||||
import '../style/OrdersList.css';
|
||||
import {setViewAllOrdersFlag} from '../../../actions/orders/ordersActions';
|
||||
import {orderTexts} from '../../../constants/ordersConstants';
|
||||
|
||||
class OrderListHeader extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
isViewAllOrdersChecked: false
|
||||
};
|
||||
this.handleInputChange = this.handleInputChange.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const isViewAllChecked = {};
|
||||
isViewAllChecked[this.props.params] = this.state.isViewAllOrdersChecked;
|
||||
this.props.dispatch(setViewAllOrdersFlag(isViewAllChecked));
|
||||
}
|
||||
|
||||
handleInputChange(e) {
|
||||
this.setState({
|
||||
isViewAllOrdersChecked: !this.state.isViewAllOrdersChecked
|
||||
});
|
||||
const isViewAllChecked = {};
|
||||
isViewAllChecked[this.props.params] = e.target.checked;
|
||||
this.props.dispatch(setViewAllOrdersFlag(isViewAllChecked));
|
||||
}
|
||||
|
||||
render() {
|
||||
const {isCompanyAdmin} = this.props;
|
||||
|
||||
return (
|
||||
<Row id="view-all-orders-checkbox">
|
||||
{isCompanyAdmin &&
|
||||
<Col xl="10">
|
||||
<Input type="checkbox"
|
||||
name="isViewAllOrdersChecked"
|
||||
checked={this.state.isViewAllOrdersChecked}
|
||||
onChange={this.handleInputChange}
|
||||
className="view-all-orders-checkbox" />
|
||||
<span className="view-all-orders-text">{orderTexts.labels.VIEW_ALL_ORDERS}</span>
|
||||
</Col>
|
||||
}
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
isCompanyAdmin: state.auth.isCompanyAdmin
|
||||
});
|
||||
export default connect(mapStateToProps)(OrderListHeader);
|
||||
92
frontend/src/containers/orders/components/OrderPackage.jsx
Normal file
92
frontend/src/containers/orders/components/OrderPackage.jsx
Normal file
@@ -0,0 +1,92 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Col} from 'reactstrap';
|
||||
import WiaasBox from '../../../mainComponents/box/WiaasBox.jsx';
|
||||
import {WiaasTable, WiaasTableHeader, WiaasTableBody, WiaasTableRow, WiaasTableCol} from '../../../mainComponents/table/WiaasTable.jsx';
|
||||
import {orderTexts} from '../../../constants/ordersConstants';
|
||||
import '../style/Orders.css';
|
||||
|
||||
class OrderPackage extends Component {
|
||||
calculateRecuringPrice(packageDetails) {
|
||||
return packageDetails.units * (parseFloat(packageDetails.packageRecuringPrice) + parseFloat(packageDetails.packageServicePrice));
|
||||
}
|
||||
|
||||
calculateQuantityPrice(quantity, price, recurringPrice = 0) {
|
||||
return quantity * parseFloat(price + recurringPrice);
|
||||
}
|
||||
|
||||
getHeadersByType(type) {
|
||||
if(type === 'active') {
|
||||
return ['Package', 'Price', 'Services and support', 'Delivery active step'];
|
||||
}
|
||||
|
||||
return ['Package', 'Price', 'Services and support', 'End of Life'];
|
||||
}
|
||||
|
||||
render() {
|
||||
const {order, type} = this.props;
|
||||
|
||||
return (
|
||||
<WiaasTableRow className={"order-border-" + order.status}>
|
||||
<Col lg="3" sm="12" xs="12">
|
||||
<WiaasBox mainTitle="Order Details">
|
||||
<div className="order-details-container">
|
||||
<WiaasTableRow id={'delivery-address-' + order.id}>
|
||||
<Col lg="4" sm="4" xs="4">{orderTexts.labels.DELIVERY_ADDRESS}:</Col>
|
||||
<Col lg="8" sm="8" xs="8">{order.deliveryAddress}</Col>
|
||||
</WiaasTableRow>
|
||||
<WiaasTableRow id={'phone-' + order.id}>
|
||||
<Col lg="4" sm="4" xs="4">{orderTexts.labels.PHONE_NUMBER}:</Col>
|
||||
<Col lg="8" sm="8" xs="8">{order.phone}</Col>
|
||||
</WiaasTableRow>
|
||||
<WiaasTableRow id={'mail-' + order.id}>
|
||||
<Col lg="4" sm="4" xs="4">{orderTexts.labels.MAIL}:</Col>
|
||||
<Col lg="8" sm="8" xs="8">{order.mail}</Col>
|
||||
</WiaasTableRow>
|
||||
<WiaasTableRow id={'commercial-lead-phone-' + order.id}>
|
||||
<Col lg="4" sm="4" xs="4">{order.clName} {orderTexts.labels.PHONE_NUMBER}:</Col>
|
||||
<Col lg="8" sm="8" xs="8">{order.commercialLeadPhone}</Col>
|
||||
</WiaasTableRow>
|
||||
<WiaasTableRow id={'mail-' + order.id}>
|
||||
<Col lg="4" sm="4" xs="4">{order.clName} {orderTexts.labels.MAIL}:</Col>
|
||||
<Col lg="8" sm="8" xs="8">{order.commercialLeadMail}</Col>
|
||||
</WiaasTableRow>
|
||||
</div>
|
||||
</WiaasBox>
|
||||
</Col>
|
||||
<Col lg="9" sm="12" xs="12">
|
||||
<WiaasBox mainTitle="Items">
|
||||
<WiaasTable>
|
||||
<WiaasTableHeader headers={this.getHeadersByType(type)}/>
|
||||
<WiaasTableBody>
|
||||
{order.packages.map((orderPackage, index) =>
|
||||
<WiaasTableRow className="order-central-row" key={orderPackage.idOrder + '-' + orderPackage.idPackage}>
|
||||
<WiaasTableCol header="Package" className="package-info-col">
|
||||
<div className="package-name">{orderPackage.units} x {orderPackage.packageName}</div>
|
||||
</WiaasTableCol>
|
||||
<WiaasTableCol header="Price">
|
||||
{this.calculateQuantityPrice(orderPackage.units, orderPackage.packageFixedPrice).toLocaleString()} {orderPackage.packageCurrency && orderPackage.packageCurrency.currency} {' '}
|
||||
({orderPackage.paymentType})
|
||||
</WiaasTableCol>
|
||||
<WiaasTableCol header="Services and support">
|
||||
{this.calculateQuantityPrice(orderPackage.units, orderPackage.packageServicePrice, orderPackage.packageRecuringPrice).toLocaleString() + ' / ' + orderPackage.periodUnit + ' '}
|
||||
{orderTexts.labels.EXTEND} {orderPackage.periodUnit} (Max {orderPackage.maxContractPeriod})
|
||||
</WiaasTableCol>
|
||||
<WiaasTableCol>
|
||||
{
|
||||
type === 'active'
|
||||
? orderPackage.shortDesc ? orderPackage.shortDesc : '-'
|
||||
: orderPackage.endOfLife ? orderPackage.endOfLife : '-'
|
||||
}
|
||||
</WiaasTableCol>
|
||||
</WiaasTableRow>
|
||||
)}
|
||||
</WiaasTableBody>
|
||||
</WiaasTable>
|
||||
</WiaasBox>
|
||||
</Col>
|
||||
</WiaasTableRow>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default OrderPackage;
|
||||
35
frontend/src/containers/orders/components/PackagesNav.jsx
Normal file
35
frontend/src/containers/orders/components/PackagesNav.jsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Row, Col} from 'reactstrap';
|
||||
import {orderTexts} from '../../../constants/ordersConstants';
|
||||
|
||||
class PackageNav extends Component {
|
||||
getClass(packageName) {
|
||||
return this.props.params.packageNameFilter === packageName ? 'process-nav-div selected-nav' : 'process-nav-div';
|
||||
}
|
||||
|
||||
render() {
|
||||
const {packages, onPackageFilter} = this.props.params;
|
||||
|
||||
return (
|
||||
<Row id="process-nav" className="process-nav">
|
||||
<Col xl="1" lg="2" md="3" sm="12" xs="12" className="process-nav-buttons">
|
||||
<div className="wiaas-main-title">
|
||||
{orderTexts.labels.PACKAGES}
|
||||
</div>
|
||||
</Col>
|
||||
<Col xl="9" lg="9" md="4" xs="12" className="process-menu">
|
||||
<div className={this.getClass('all')} onClick={()=>{onPackageFilter('all')}}>{orderTexts.buttons.ALL}</div>
|
||||
{
|
||||
packages.length > 0 &&
|
||||
packages.map((orderPackage) => <div key={'menu-package-' + orderPackage.idPackage}
|
||||
onClick={()=>{onPackageFilter(orderPackage.packageName)}}
|
||||
className={this.getClass(orderPackage.packageName)}>{orderPackage.packageName}</div>)
|
||||
}
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PackageNav;
|
||||
121
frontend/src/containers/orders/components/SupportMail.jsx
Normal file
121
frontend/src/containers/orders/components/SupportMail.jsx
Normal file
@@ -0,0 +1,121 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import {Row, Col, FormGroup, Label, Input} from 'reactstrap';
|
||||
import {setSupportMessage} from '../../../actions/orders/processActions';
|
||||
import {orderTexts} from '../../../constants/ordersConstants';
|
||||
|
||||
class SupportMail extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
supportText: ''
|
||||
};
|
||||
this.setSupportMessage = this.setSupportMessage.bind(this);
|
||||
}
|
||||
calculateFixedPrice(quantity, price) {
|
||||
return quantity*price;
|
||||
}
|
||||
|
||||
calculateRecurrentPrice(orderPackage) {
|
||||
return orderPackage.units*(orderPackage.packageRecuringPrice + orderPackage.packageServicePrice);
|
||||
}
|
||||
|
||||
handleInputChange(event) {
|
||||
this.setState({supportText: event.target.value});
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
setSupportMessage() {
|
||||
this.props.dispatch(setSupportMessage(this.state.supportText));
|
||||
}
|
||||
|
||||
render() {
|
||||
const {orderInfo, orderPackages} = this.props.params;
|
||||
|
||||
return (
|
||||
<span id="send-support-mail-container">
|
||||
{orderInfo && orderPackages &&
|
||||
<div>
|
||||
<div id="order-details">
|
||||
<Row>
|
||||
<Col>
|
||||
<h5>{orderTexts.labels.ORDER_DETAILS}</h5>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col xl="4">
|
||||
<span className="subtitle">{orderTexts.labels.ORDER_NUMBER}:</span>
|
||||
</Col>
|
||||
<Col xl="8">
|
||||
<span>{orderInfo.orderNumber}</span>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col xl="4">
|
||||
<span className="subtitle">{orderTexts.labels.LOCATION_DETAILS}:</span>
|
||||
</Col>
|
||||
<Col xl="8">
|
||||
<span>{orderInfo.reference || '-'}</span>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<div id="order-items" className="support-details">
|
||||
<Row>
|
||||
<Col>
|
||||
<h5>{orderTexts.labels.ORDER_ITEMS}</h5>
|
||||
</Col>
|
||||
</Row>
|
||||
{ orderPackages.map((orderPackage, mapKey) =>
|
||||
<div key={'order-package-'+mapKey} className="order-package-details">
|
||||
<Row>
|
||||
<Col>
|
||||
<span className="fa fa-shopping-cart subtitle"></span>
|
||||
<span className="package-name"> {orderPackage.units} x {orderPackage.packageName}</span>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{orderPackage.endOfLife &&
|
||||
<Row>
|
||||
<Col>
|
||||
<span className="subtitle">{orderTexts.labels.END_OF_LIFE}:</span>
|
||||
</Col>
|
||||
<Col xl="8">
|
||||
<span>{orderPackage.endOfLife}</span>
|
||||
</Col>
|
||||
</Row>
|
||||
}
|
||||
<Row>
|
||||
<Col>
|
||||
<span className="subtitle">{orderTexts.labels.STATUS}:</span>
|
||||
</Col>
|
||||
<Col xl="8">
|
||||
<span>{orderPackage.status}</span>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div id="order-support-text" className="support-details">
|
||||
<Row>
|
||||
<Col>
|
||||
<FormGroup>
|
||||
<Label for="supportText">{orderTexts.labels.ENTER_TEXT}</Label>
|
||||
<Input id="my-support-mail-text"
|
||||
type="textarea"
|
||||
name="supportText"
|
||||
value={this.state.supportText}
|
||||
onChange={(e) => this.handleInputChange(e)}
|
||||
onBlur={this.setSupportMessage}/>
|
||||
</FormGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default connect()(SupportMail);
|
||||
@@ -0,0 +1,165 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
import moment from 'moment';
|
||||
import {Row, Col, Button, Popover, PopoverBody} from 'reactstrap';
|
||||
import '../../style/InstallationScheduling.css';
|
||||
import {updateInstallationDate, removeMyDate, setSchedulingFlag} from '../../../../actions/orders/processActions';
|
||||
import {setDialogContent, setDialogOpenFlag} from '../../../../actions/dialog/dialogActions';
|
||||
import {orderTexts} from '../../../../constants/ordersConstants';
|
||||
|
||||
class InstallationSchedulingDatesPerPackage extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
startDate: undefined,
|
||||
btnType: '',
|
||||
nestedModal: false,
|
||||
closeAll: false,
|
||||
popoverOpen: false
|
||||
};
|
||||
this.toggle = this.toggle.bind(this);
|
||||
this.openInstallationDialog = this.openInstallationDialog.bind(this);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.handleBtnClick = this.handleBtnClick.bind(this);
|
||||
this.handleBtnAction = this.handleBtnAction.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.dispatch(setSchedulingFlag(this.props.installationParams.isSchedulingDisabled));
|
||||
}
|
||||
|
||||
handleChange(date) {
|
||||
this.setState({startDate: date});
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.setState({
|
||||
popoverOpen: !this.state.popoverOpen
|
||||
});
|
||||
}
|
||||
|
||||
canUserAcceptOrDecline(dateInfo, lastStatus) {
|
||||
let additionalCondition = false;
|
||||
if (lastStatus === 'declined') {
|
||||
additionalCondition = dateInfo.lastStatus === 'canceled' && dateInfo.isProposedByMe;
|
||||
}
|
||||
return !this.props.isComponentDisabled &&
|
||||
((dateInfo.lastStatus === 'proposed' && !dateInfo.isProposedByMe) ||
|
||||
(dateInfo.lastStatus === lastStatus && dateInfo.isProposedByMe) ||
|
||||
additionalCondition);
|
||||
}
|
||||
|
||||
isDateProposedByMe() {
|
||||
return this.props.dateInfo.lastStatus === 'proposed' && this.props.dateInfo.isProposedByMe === true;
|
||||
}
|
||||
|
||||
isRemoveBtnVisible(confirmationDate) {
|
||||
return !this.props.isComponentDisabled && this.isDateProposedByMe();
|
||||
}
|
||||
|
||||
handleBtnClick(type) {
|
||||
this.setState({type});
|
||||
const upperCaseType = type.charAt(0).toUpperCase() + type.slice(1);
|
||||
const dialogInstallationContent = {
|
||||
buttons: [
|
||||
{
|
||||
color: 'success',
|
||||
action: this.handleBtnAction,
|
||||
name: orderTexts.buttons.YES,
|
||||
id: type + '-installation-date-confirmation'
|
||||
}, {
|
||||
color: 'secondary',
|
||||
name: orderTexts.buttons.NO,
|
||||
action: this.openInstallationDialog,
|
||||
id: 'cancel-' + type + '-installation-date'
|
||||
}
|
||||
],
|
||||
header: upperCaseType + ' installation date confirmation',
|
||||
body: 'Are you sure you want to ' + type + ' the installation date proposed?'
|
||||
};
|
||||
|
||||
this.props.dispatch(setDialogOpenFlag(true));
|
||||
this.props.dispatch(setDialogContent(dialogInstallationContent));
|
||||
}
|
||||
|
||||
openInstallationDialog() {
|
||||
this.props.openDialogInstallContent(this.props.installationParams);
|
||||
}
|
||||
|
||||
handleBtnAction() {
|
||||
let handleFunction = this.state.type === 'remove' ? removeMyDate : updateInstallationDate;
|
||||
this.props.dispatch(handleFunction(this.props.orderPackage.idOrder, this.props.orderPackage.idPackage, this.props.confirmationDate, this.state.type));
|
||||
this.openInstallationDialog();
|
||||
}
|
||||
|
||||
getStatusIcon(status) {
|
||||
const statusesIcons = {
|
||||
proposed: 'clock-o',
|
||||
accepted: 'check',
|
||||
canceled: 'remove',
|
||||
declined: 'ban',
|
||||
invalid: 'remove'
|
||||
};
|
||||
|
||||
return 'status-icon-installation-dates fa fa-' + statusesIcons[status];
|
||||
}
|
||||
|
||||
render() {
|
||||
const {confirmationDate, dateInfo, orderPackage} = this.props;
|
||||
const idOrderPackageDatePair = orderPackage.idOrder + '-' + orderPackage.idPackage + '-' + confirmationDate;
|
||||
|
||||
return (
|
||||
<div id={"installation-scheduling-dates-container-" + idOrderPackageDatePair} className="installation-scheduling-dates-container">
|
||||
<span className="installation-date">
|
||||
<span className={this.getStatusIcon(dateInfo.lastStatus) + ' confirmation-' + dateInfo.lastStatus}></span>
|
||||
<span className="installation-date-proposed">{moment(confirmationDate).format('Do MMM, YYYY')}</span>
|
||||
<i className="dates-info-btn fa fa-info-circle"
|
||||
id={'dates-info-' + idOrderPackageDatePair}
|
||||
onClick={this.toggle}></i>
|
||||
<Popover placement="bottom"
|
||||
isOpen={this.state.popoverOpen}
|
||||
target={'dates-info-' + idOrderPackageDatePair}
|
||||
container={"installation-scheduling-dates-container-" + idOrderPackageDatePair}
|
||||
className="dates-info-popover"
|
||||
toggle={this.toggle}>
|
||||
<PopoverBody>
|
||||
{ dateInfo && dateInfo.details &&
|
||||
dateInfo.details.map((details) =>
|
||||
<Row key={'confirmation-date-details-' + details.currentDate}>
|
||||
<Col>
|
||||
{moment(details.currentDate).format('Do MMM, YYYY LT')}
|
||||
</Col>
|
||||
<Col className={"confirmation-" + details.status}>
|
||||
<span className={this.getStatusIcon(details.status)}></span>
|
||||
{details.status}
|
||||
</Col>
|
||||
<Col>
|
||||
{details.username} ({details.userType})
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
</PopoverBody>
|
||||
</Popover>
|
||||
</span>
|
||||
<span className="confirmation-dates-buttons">
|
||||
{ this.canUserAcceptOrDecline(dateInfo, 'declined') &&
|
||||
<Button id={"accept-date-"+idOrderPackageDatePair} className="installation-button install-btn-accept" onClick={() => {this.handleBtnClick('accept')}} >{orderTexts.buttons.ACCEPT}</Button>
|
||||
}
|
||||
{ this.canUserAcceptOrDecline(dateInfo, 'accepted') &&
|
||||
<Button id={"decline-date-"+idOrderPackageDatePair} className="installation-button install-btn-decline" onClick={() => {this.handleBtnClick('decline')}} >{orderTexts.buttons.DECLINE}</Button>
|
||||
}
|
||||
{ this.isRemoveBtnVisible(confirmationDate) &&
|
||||
<Button id={"cancel-remove-installation-dates-"+idOrderPackageDatePair} className="installation-button install-btn-remove" onClick={() => {this.handleBtnClick('remove')}} >{orderTexts.buttons.REMOVE}</Button>
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
confirmationDates: state.processReducer.confirmationDates
|
||||
});
|
||||
export default connect(mapStateToProps)(InstallationSchedulingDatesPerPackage);
|
||||
@@ -0,0 +1,175 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import moment from 'moment';
|
||||
import {Row, Col, Popover, PopoverBody} from 'reactstrap';
|
||||
import '../../style/InstallationScheduling.css';
|
||||
import InstallationSchedulingPerPackage from './InstallationSchedulingPerPackage.jsx';
|
||||
import {orderTexts} from '../../../../constants/ordersConstants';
|
||||
import {setDialogContent, setDialogOpenFlag} from '../../../../actions/dialog/dialogActions';
|
||||
|
||||
class InstallationSchedulingForPackages extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
popoverOpen: false
|
||||
}
|
||||
|
||||
this.toggle = this.toggle.bind(this);
|
||||
this.setContentDialog = this.setContentDialog.bind(this);
|
||||
this.openDialogInstallContent = this.openDialogInstallContent.bind(this);
|
||||
}
|
||||
|
||||
setContentDialog(installationParams) {
|
||||
return {
|
||||
class: 'installation-scheduling',
|
||||
hasCloseIcon: true,
|
||||
header: orderTexts.labels.INSTALLATION_SCHEDULE_HEADER,
|
||||
TagName: InstallationSchedulingPerPackage,
|
||||
params: {installationParams, openDialogInstallContent: this.openDialogInstallContent}
|
||||
};
|
||||
}
|
||||
|
||||
openDialogInstallContent(installationParams) {
|
||||
const dialogContent = this.setContentDialog(installationParams);
|
||||
|
||||
this.props.dispatch(setDialogOpenFlag(true));
|
||||
this.props.dispatch(setDialogContent(dialogContent));
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.setState({
|
||||
popoverOpen: !this.state.popoverOpen
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {orderPackage, areComponentsDisabled, isInstallationSet, isInstallationInPackage, noOfPackages, installCompanies, isComponentDisabled, earliestInstallDate, confirmationDates, areAllShippingDatesConfirmed} = this.props;
|
||||
const idOrder = orderPackage ? orderPackage.idOrder : 0;
|
||||
const idOrderPackagePair = orderPackage ? idOrder + '-' + orderPackage.idPackage : '';
|
||||
const acceptedDate = {};
|
||||
const proposedDate = {};
|
||||
const installationCompany = {};
|
||||
const availableCompanies = {};
|
||||
const selectedCompanies = {};
|
||||
const isPreliminaryInstallationDate = {};
|
||||
|
||||
if(confirmationDates && confirmationDates[idOrderPackagePair]) {
|
||||
const packageDates = confirmationDates[idOrderPackagePair];
|
||||
const accepted = Object.keys(packageDates).find(installDate => {return packageDates[installDate].lastStatus === 'accepted'});
|
||||
acceptedDate[idOrderPackagePair] = accepted ? moment(accepted).format('Do MMM, YYYY') : '';
|
||||
const proposed = Object.keys(packageDates).find(installDate => {return packageDates[installDate].lastStatus === 'proposed'});
|
||||
proposedDate[idOrderPackagePair] = proposed ? moment(proposed).format('Do MMM, YYYY') : '';
|
||||
}
|
||||
|
||||
if(installCompanies) {
|
||||
availableCompanies[idOrderPackagePair] = idOrderPackagePair in installCompanies.available ? installCompanies.available[idOrderPackagePair] : [];
|
||||
selectedCompanies[idOrderPackagePair] = idOrderPackagePair in installCompanies.selected ? installCompanies.selected[idOrderPackagePair] : {};
|
||||
if (idOrderPackagePair in selectedCompanies && Object.keys(selectedCompanies[idOrderPackagePair]).length > 0) {
|
||||
installationCompany[idOrderPackagePair] = selectedCompanies[idOrderPackagePair];
|
||||
}
|
||||
}
|
||||
|
||||
isPreliminaryInstallationDate[idOrderPackagePair] = areAllShippingDatesConfirmed && orderPackage.idOrder in areAllShippingDatesConfirmed ? !areAllShippingDatesConfirmed[orderPackage.idOrder] : true;
|
||||
const isSchedulingDisabled = (idOrder in areComponentsDisabled && areComponentsDisabled[idOrder]) || (isInstallationSet && !isInstallationSet[idOrderPackagePair]);
|
||||
|
||||
const installationParams = {
|
||||
idOrder,
|
||||
idOrderPackagePair,
|
||||
orderPackage,
|
||||
installCompanies,
|
||||
isComponentDisabled,
|
||||
earliestInstallDate,
|
||||
confirmationDates,
|
||||
isThisComponentDisabled: areComponentsDisabled[idOrder],
|
||||
availableCompanies,
|
||||
selectedCompanies,
|
||||
installationCompany,
|
||||
isSchedulingDisabled,
|
||||
isInstallationSet,
|
||||
isPreliminaryInstallationDate,
|
||||
acceptedDate,
|
||||
proposedDate
|
||||
};
|
||||
|
||||
return (
|
||||
<span id="installation-scheduler-container">
|
||||
{ noOfPackages === 1
|
||||
? this.openDialogInstallContent(installationParams)
|
||||
: <Row className="package-installation-row">
|
||||
<Col xl="7" id={"package-name-" + orderPackage.idOrder + '-' + orderPackage.idPackage}>
|
||||
{orderPackage.packageName}
|
||||
</Col>
|
||||
<Col xl="5">
|
||||
<div className="subtitle">
|
||||
{
|
||||
isInstallationInPackage && isInstallationInPackage[idOrderPackagePair] === false
|
||||
? <span>{orderTexts.labels.INSTALLATION_NOT_REQUIRED}</span>
|
||||
: isPreliminaryInstallationDate[idOrderPackagePair]
|
||||
? <span>{orderTexts.labels.PRELIMINARY_INSTALLATION_DATE_LABEL}: </span>
|
||||
: <span>{orderTexts.labels.INSTALLATION_DATE}: </span>
|
||||
}
|
||||
</div>
|
||||
<div id={"installation-scheduler-container-" + idOrderPackagePair} className="install-date-text">
|
||||
{
|
||||
isSchedulingDisabled
|
||||
? acceptedDate[idOrderPackagePair]
|
||||
? acceptedDate[idOrderPackagePair]
|
||||
: proposedDate[idOrderPackagePair]
|
||||
? proposedDate[idOrderPackagePair]
|
||||
: (isInstallationInPackage[idOrderPackagePair] && !proposedDate[idOrderPackagePair] && !acceptedDate[idOrderPackagePair]) && orderTexts.labels.NOT_SET
|
||||
: <span className="check-installation-dates"
|
||||
onClick={() => this.openDialogInstallContent(installationParams)}>
|
||||
{
|
||||
acceptedDate[idOrderPackagePair]
|
||||
? acceptedDate[idOrderPackagePair]
|
||||
: proposedDate[idOrderPackagePair]
|
||||
? proposedDate[idOrderPackagePair]
|
||||
: (isInstallationInPackage[idOrderPackagePair] && !proposedDate[idOrderPackagePair] && !acceptedDate[idOrderPackagePair]) && orderTexts.labels.NOT_SET
|
||||
}
|
||||
</span>
|
||||
}
|
||||
{
|
||||
isInstallationInPackage[idOrderPackagePair] &&
|
||||
<span>
|
||||
<i className="scheduled-date-btn fa fa-info-circle"
|
||||
id={'scheduled-date-' + idOrderPackagePair}
|
||||
onClick={this.toggle}></i>
|
||||
<Popover placement="bottom"
|
||||
isOpen={this.state.popoverOpen}
|
||||
target={'scheduled-date-' + idOrderPackagePair}
|
||||
container={"installation-scheduler-container-" + idOrderPackagePair}
|
||||
className="scheduled-date-popover"
|
||||
toggle={this.toggle}>
|
||||
<PopoverBody>
|
||||
{
|
||||
isPreliminaryInstallationDate[idOrderPackagePair]
|
||||
? acceptedDate[idOrderPackagePair]
|
||||
? orderTexts.labels.PRELIMINARY_INSTALLATION_DATE
|
||||
: orderTexts.labels.INSTALLATION_DATE_NOT_SET
|
||||
: acceptedDate[idOrderPackagePair]
|
||||
? orderTexts.labels.INSTALLATION_DATE_ACCEPTED
|
||||
: orderTexts.labels.INSTALLATION_DATE_NOT_SET
|
||||
}
|
||||
</PopoverBody>
|
||||
</Popover>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
isNextStepWanted: state.processReducer.isNextStepWanted,
|
||||
isComponentDisabled: state.processReducer.isComponentDisabled,
|
||||
earliestInstallDate: state.processReducer.earliestInstallDate,
|
||||
confirmationDates: state.processReducer.confirmationDates,
|
||||
installCompanies: state.processReducer.installCompanies
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(InstallationSchedulingForPackages);
|
||||
@@ -0,0 +1,161 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import DatePicker from 'react-datepicker';
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
import moment from 'moment';
|
||||
import {Col, Button, Popover, PopoverBody} from 'reactstrap';
|
||||
import '../../style/InstallationScheduling.css';
|
||||
import {API_SERVER} from '../../../../config';
|
||||
import FileDownloader from '../../../../helpers/FileDownloader';
|
||||
import InstallationSchedulingDatesPerPackage from './InstallationSchedulingDatesPerPackage.jsx';
|
||||
import {updateInstallationDate} from '../../../../actions/orders/processActions';
|
||||
import {orderTexts} from '../../../../constants/ordersConstants';
|
||||
|
||||
const fileHandler = new FileDownloader();
|
||||
const fileType = 'installationProtocol';
|
||||
const status = 'proposed';
|
||||
|
||||
class InstallationSchedulingPerPackage extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
startDate: undefined
|
||||
};
|
||||
this.toggle = this.toggle.bind(this);
|
||||
this.handleDateChange = this.handleDateChange.bind(this);
|
||||
this.handleSelect = this.handleSelect.bind(this);
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.setState({
|
||||
popoverOpen: !this.state.popoverOpen
|
||||
});
|
||||
}
|
||||
|
||||
handleDateChange(startDate) {
|
||||
this.setState({startDate});
|
||||
}
|
||||
|
||||
handleSelect(date, idOrder, idPackage) {
|
||||
const newDate = new Date(moment(date).toISOString());
|
||||
this.handleDateChange(date);
|
||||
this.toggle();
|
||||
|
||||
if(Date.parse(newDate)) {
|
||||
const updateDate = moment(date).format('YYYY-MM-DD');
|
||||
this.props.dispatch(updateInstallationDate(idOrder, idPackage, updateDate, status, this.handleDateChange));
|
||||
}
|
||||
}
|
||||
|
||||
downloadDocument(document){
|
||||
const fileUrl = `${API_SERVER}/utils/api/downloadFile?idDocument=${document.idDocument}&fileName=${document.documentName}.${document.extension}&fileType=${fileType}`
|
||||
const fileName = document.documentName + '.' + document.extension;
|
||||
fileHandler.download(fileUrl, fileName);
|
||||
}
|
||||
|
||||
render() {
|
||||
const acceptedDate = {};
|
||||
const proposedDate = {};
|
||||
const {
|
||||
idOrder,
|
||||
idOrderPackagePair,
|
||||
orderPackage,
|
||||
earliestInstallDate,
|
||||
isThisComponentDisabled,
|
||||
isPreliminaryInstallationDate,
|
||||
installationCompany,
|
||||
isInstallationSet
|
||||
} = this.props.params.installationParams;
|
||||
const {confirmationDates} = this.props;
|
||||
const earliestInstallationDate = earliestInstallDate && moment(earliestInstallDate[idOrder]);
|
||||
if(confirmationDates && confirmationDates[idOrderPackagePair]) {
|
||||
const packageDates = confirmationDates[idOrderPackagePair];
|
||||
const accepted = Object.keys(packageDates).find(installDate => {return packageDates[installDate].lastStatus === 'accepted'});
|
||||
acceptedDate[idOrderPackagePair] = accepted ? moment(accepted).format('Do MMM, YYYY') : '';
|
||||
const proposed = Object.keys(packageDates).find(installDate => {return packageDates[installDate].lastStatus === 'proposed'});
|
||||
proposedDate[idOrderPackagePair] = proposed ? moment(proposed).format('Do MMM, YYYY') : '';
|
||||
}
|
||||
|
||||
return (
|
||||
<fieldset disabled={isThisComponentDisabled} className="set-installation-dates">
|
||||
<Col>
|
||||
<div className="subtitle">
|
||||
{
|
||||
isPreliminaryInstallationDate[idOrderPackagePair]
|
||||
? <h6>{orderTexts.labels.PRELIMINARY_INSTALLATION_DATE_LABEL}: </h6>
|
||||
: <h6>{orderTexts.labels.INSTALLATION_DATE}: </h6>
|
||||
}
|
||||
</div>
|
||||
<div id={"installation-scheduler-container-" + idOrderPackagePair} className="install-date-text">
|
||||
{
|
||||
acceptedDate[idOrderPackagePair]
|
||||
? acceptedDate[idOrderPackagePair]
|
||||
: proposedDate[idOrderPackagePair]
|
||||
? proposedDate[idOrderPackagePair]
|
||||
: (!proposedDate[idOrderPackagePair] && !acceptedDate[idOrderPackagePair]) && orderTexts.labels.NOT_SET
|
||||
}
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
|
||||
<Col>
|
||||
<div className="subtitle"><h6>{orderTexts.labels.INSTALL_COMPANY}:</h6></div>
|
||||
<span id={"installation-company-name-" + idOrderPackagePair}>
|
||||
{ isInstallationSet[idOrderPackagePair] ? installationCompany[idOrderPackagePair].name : <span>{orderTexts.labels.INSTALL_COMPANY_NOT_SET}</span>}
|
||||
</span>
|
||||
</Col>
|
||||
<Col>
|
||||
<div className="subtitle"><h6>{orderTexts.labels.EARLIEST_INSTALLATION}:</h6></div>
|
||||
<span id={"earliest-installation-date-" + idOrderPackagePair}>
|
||||
{(earliestInstallDate && earliestInstallDate[idOrder])
|
||||
? moment(earliestInstallDate[idOrder]).format('Do MMM, YYYY')
|
||||
: '-'}
|
||||
</span>
|
||||
</Col>
|
||||
<Col>
|
||||
<div className="subtitle"><h6>{orderTexts.labels.PROPOSED_DATES}</h6></div>
|
||||
{
|
||||
confirmationDates && confirmationDates[idOrderPackagePair]
|
||||
&& Object.keys(confirmationDates[idOrderPackagePair]).map((confirmationDate) =>
|
||||
<InstallationSchedulingDatesPerPackage
|
||||
key={'order-package-installation-dates-' + confirmationDate}
|
||||
minDate={earliestInstallationDate}
|
||||
confirmationDate={confirmationDate}
|
||||
dateInfo={confirmationDates[idOrderPackagePair][confirmationDate]}
|
||||
orderPackage={orderPackage}
|
||||
openDialogInstallContent={this.props.params.openDialogInstallContent}
|
||||
installationParams={this.props.params.installationParams}
|
||||
isComponentDisabled={isThisComponentDisabled}/>)
|
||||
}
|
||||
</Col>
|
||||
<Col id={"installation-scheduling-propose-date-" + idOrderPackagePair}>
|
||||
<Button id={"propose-new-installation-date-" + idOrderPackagePair} disabled={isThisComponentDisabled} className="propose-new-date-btn" onClick={this.toggle}>Add optional date</Button>
|
||||
<Popover placement="bottom"
|
||||
isOpen={this.state.popoverOpen}
|
||||
target={"propose-new-installation-date-" + idOrderPackagePair}
|
||||
container={"installation-scheduling-propose-date-" + idOrderPackagePair}
|
||||
className="dates-info-popover"
|
||||
toggle={this.toggle}>
|
||||
<PopoverBody>
|
||||
<DatePicker
|
||||
inline
|
||||
id={"installation-date-propose-" + idOrderPackagePair}
|
||||
selected={this.state.startDate}
|
||||
onSelect={(date) => this.handleSelect(date, orderPackage.idOrder, orderPackage.idPackage)}
|
||||
minDate={earliestInstallationDate}
|
||||
dateFormat="Do MMM, YYYY"
|
||||
placeholderText="Choose a date" />
|
||||
</PopoverBody>
|
||||
</Popover>
|
||||
</Col>
|
||||
</fieldset>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
confirmationDates: state.processReducer.confirmationDates
|
||||
});
|
||||
export default connect(mapStateToProps)(InstallationSchedulingPerPackage);
|
||||
@@ -0,0 +1,142 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Row, Col, Container, Popover, PopoverBody, PopoverHeader} from 'reactstrap';
|
||||
import {API_SERVER} from '../../../../config';
|
||||
import FileDownloader from '../../../../helpers/FileDownloader';
|
||||
import {orderTexts} from '../../../../constants/ordersConstants';
|
||||
|
||||
const fileHandler = new FileDownloader();
|
||||
|
||||
class PackageInfo extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.toggle = this.toggle.bind(this);
|
||||
this.state = {
|
||||
popoverOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.setState({
|
||||
popoverOpen: !this.state.popoverOpen
|
||||
});
|
||||
}
|
||||
|
||||
downloadDocument(document){
|
||||
const fileUrl = `${API_SERVER}/utils/api/downloadFile?idDocument=${document.idDocument}&fileName=${document.documentName}.${document.extension}&fileType=${document.documentTypeName}`
|
||||
const fileName = document.documentName + '.' + document.extension;
|
||||
fileHandler.download(fileUrl, fileName);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {orderPackage, onViewChange} = this.props;
|
||||
const shouldShowPriceInfo = orderPackage.packageRecuringPrice > 0 || orderPackage.packageServicePrice > 0;
|
||||
|
||||
return (
|
||||
<Container fluid={true} id="package-info" className="order-package-info">
|
||||
<Row>
|
||||
<Col xl="3">
|
||||
<div className="subtitle">
|
||||
<h6>
|
||||
{orderTexts.labels.PACKAGE_PRICE}: {' '}
|
||||
{ shouldShowPriceInfo &&
|
||||
<i className="price-info-btn fa fa-info-circle"
|
||||
id={'price-info-' + orderPackage.idPackage}
|
||||
onClick={this.toggle}></i>
|
||||
}
|
||||
</h6>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
{orderTexts.labels.TOTAL_DELVIERY_PRICE}: {' '}
|
||||
{(orderPackage.units * orderPackage.packageFixedPrice).toLocaleString() + ' ' + orderPackage.packageCurrency.currency}
|
||||
</div>
|
||||
{
|
||||
shouldShowPriceInfo &&
|
||||
<div>
|
||||
{orderTexts.labels.TOTAL_RECURRENT_PRICE}:{' '}
|
||||
{(orderPackage.units * (orderPackage.packageRecuringPrice + orderPackage.packageServicePrice)).toLocaleString()} {orderPackage.packageCurrency.currency}
|
||||
</div>
|
||||
}
|
||||
|
||||
{ shouldShowPriceInfo &&
|
||||
<Popover placement="bottom"
|
||||
isOpen={this.state.popoverOpen}
|
||||
target={'price-info-' + orderPackage.idPackage}
|
||||
container={'price-info-' + orderPackage.idPackage}
|
||||
className="price-info-popover"
|
||||
toggle={this.toggle}>
|
||||
<PopoverHeader>{orderPackage.paymentType}</PopoverHeader>
|
||||
<PopoverBody>
|
||||
<div>
|
||||
{ orderPackage.packageRecuringPrice > 0 &&
|
||||
<div className="package-price-recurrent">
|
||||
<span className="price-info-title">{orderTexts.labels.RECURRENT_PRICE}: </span>
|
||||
{(orderPackage.units * orderPackage.packageRecuringPrice).toLocaleString()} {orderPackage.packageCurrency.currency} / {orderPackage.periodUnit}
|
||||
{
|
||||
orderPackage.packagePayPeriod > 0 &&
|
||||
<span>
|
||||
for {orderPackage.packagePayPeriod} {orderPackage.periodUnit}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
{ orderPackage.packageServicePrice > 0 &&
|
||||
<div className="services-price-recurrent">
|
||||
<span className="price-info-title">{orderTexts.labels.SERVICES_PRICE}: </span>
|
||||
{(orderPackage.units * orderPackage.packageServicePrice).toLocaleString()} {orderPackage.packageCurrency.currency} / {orderPackage.periodUnit}
|
||||
{
|
||||
orderPackage.servicesContractPeriod > 0 &&
|
||||
<span>
|
||||
for {orderPackage.servicesContractPeriod} {orderPackage.periodUnit}
|
||||
</span>
|
||||
}
|
||||
<span> {orderTexts.labels.EXTEND} {orderPackage.periodUnit} (Max {orderPackage.maxContractPeriod} {orderPackage.periodUnit})</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</PopoverBody>
|
||||
</Popover>
|
||||
}
|
||||
</Col>
|
||||
{
|
||||
orderPackage.options.length > 0 &&
|
||||
<Col xl="3">
|
||||
<div className="subtitle"><h6>{orderTexts.labels.OPTIONS}:</h6></div>
|
||||
{
|
||||
orderPackage.options.map((option, index) => <div key={'option-'+index}>
|
||||
{option.groupName}: {option.packageName}
|
||||
</div>)
|
||||
}
|
||||
</Col>
|
||||
}
|
||||
{
|
||||
orderPackage.additionalPackages.length > 0 &&
|
||||
<Col xl="3">
|
||||
<div className="subtitle"><h6>{orderTexts.labels.ADDITIONAL_PACKAGES}:</h6></div>
|
||||
{
|
||||
orderPackage.additionalPackages.map((additional, index) => <div key={'additional-'+index}>
|
||||
{additional.packageName}
|
||||
</div>)
|
||||
}
|
||||
</Col>
|
||||
}
|
||||
{
|
||||
orderPackage.documents &&
|
||||
<Col xl="2">
|
||||
<div className="subtitle"><h6>{orderTexts.labels.DOCUMENTS}:</h6></div>
|
||||
{
|
||||
orderPackage.documents.length > 0 ?
|
||||
<div className="link-to-docs" onClick={()=>onViewChange('documents')}>{orderTexts.buttons.SEE_DOCUMENTS}</div>:
|
||||
<span>{orderTexts.labels.NO_DOCUMENTS}</span>
|
||||
}
|
||||
</Col>
|
||||
}
|
||||
</Row>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PackageInfo;
|
||||
@@ -0,0 +1,16 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Link} from 'react-router-dom';
|
||||
|
||||
class PackageName extends Component {
|
||||
render(){
|
||||
const {orderPackage, idCommercialLead} = this.props.params;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Link to={'/co-market/' + idCommercialLead + '/' + orderPackage.idPackage } className="package-name-link">{orderPackage.units + ' x ' + orderPackage.packageName}</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PackageName;
|
||||
@@ -0,0 +1,23 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Row, Col} from 'reactstrap';
|
||||
import WiaasBox from '../../../../mainComponents/box/WiaasBox.jsx';
|
||||
import PackageInfo from './PackageInfo.jsx';
|
||||
import PackageName from './PackageName.jsx';
|
||||
|
||||
class ProcessPackage extends Component {
|
||||
render() {
|
||||
const {orderPackage, idCommercialLead} = this.props;
|
||||
|
||||
return (
|
||||
<WiaasBox customHeader={PackageName} customHeaderParams={{orderPackage, idCommercialLead}} className="order-package">
|
||||
<Row>
|
||||
<Col xl="12" lg="12" md="12" xs="12">
|
||||
<PackageInfo onViewChange={this.props.onViewChange} orderPackage={orderPackage}/>
|
||||
</Col>
|
||||
</Row>
|
||||
</WiaasBox>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ProcessPackage;
|
||||
@@ -0,0 +1,30 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Input} from 'reactstrap';
|
||||
import {orderTexts} from '../../../../constants/ordersConstants';
|
||||
|
||||
class AcceptanceDeclineReason extends Component {
|
||||
handleEditorChange = (e) => {
|
||||
const reason = e.target.value;
|
||||
this.props.params.onEditorChange(reason);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {actionType} = this.props.params;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
actionType === 'accept'
|
||||
? <div>{orderTexts.labels.ACCEPT_INSTALLATION_TEXT}</div>
|
||||
: <div>
|
||||
<div>{orderTexts.labels.DECLINE_REASON_TEXT}</div>
|
||||
<Input onChange={this.handleEditorChange} type="textarea" name="acceptance-decline-reason" id="installation-declined-reason" />
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AcceptanceDeclineReason;
|
||||
@@ -0,0 +1,193 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import Dropzone from 'react-dropzone';
|
||||
import {Row, Col, Button} from 'reactstrap';
|
||||
import {fetchCustomerAcceptance, uploadAcceptance, acceptDeclineInstallation, badFile} from '../../../../actions/orders/customerAcceptanceActions';
|
||||
import {setDialogContent, setDialogOpenFlag} from '../../../../actions/dialog/dialogActions';
|
||||
import AcceptanceDeclineReason from './AcceptanceDeclineReason.jsx';
|
||||
import {API_SERVER} from '../../../../config';
|
||||
import FileDownloader from '../../../../helpers/FileDownloader';
|
||||
import {orderTexts} from '../../../../constants/ordersConstants';
|
||||
import '../../style/CustomerAcceptance.css';
|
||||
|
||||
const fileHandler = new FileDownloader();
|
||||
|
||||
class CustomerAcceptance extends Component {
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
reason : '',
|
||||
actionType : ''
|
||||
}
|
||||
|
||||
this.acceptDeclineInstallation = this.acceptDeclineInstallation.bind(this);
|
||||
this.onEditorChange = this.onEditorChange.bind(this);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
uploadFile(idOrder, acceptedFiles, rejectedFiles) {
|
||||
if(acceptedFiles && acceptedFiles.length){
|
||||
const file = acceptedFiles[0];
|
||||
this.props.dispatch(uploadAcceptance(idOrder, file));
|
||||
}
|
||||
|
||||
if(rejectedFiles && rejectedFiles.length) {
|
||||
this.props.dispatch(badFile());
|
||||
}
|
||||
}
|
||||
|
||||
getAcceptanceStatusClass(acceptance, daysDiff) {
|
||||
const statuses = {
|
||||
0 : 'waiting',
|
||||
1 : 'accepted',
|
||||
'-1' : 'declined'
|
||||
};
|
||||
|
||||
if(acceptance === 0 && daysDiff <= 0){
|
||||
return 'danger';
|
||||
} else if(acceptance === 0 && daysDiff <= 3) {
|
||||
return 'warning';
|
||||
}else{
|
||||
return statuses[acceptance];
|
||||
}
|
||||
}
|
||||
|
||||
acceptDeclineInstallation() {
|
||||
const {idOrder} = this.props.step;
|
||||
const {actionType, reason} = this.state;
|
||||
this.props.dispatch(acceptDeclineInstallation(idOrder, actionType, reason));
|
||||
this.setState({reason: ''});
|
||||
}
|
||||
|
||||
getAcceptanceMessage(customerAcceptance){
|
||||
const messages = {
|
||||
0 : orderTexts.labels.NOT_ACCEPTED + (customerAcceptance.acceptanceDueDate || orderTexts.labels.NOT_SET),
|
||||
1 : orderTexts.labels.ACCEPTED,
|
||||
'-1' : orderTexts.labels.DECLINED
|
||||
}
|
||||
|
||||
return messages[customerAcceptance.customerAccepted];
|
||||
}
|
||||
|
||||
onEditorChange(reason) {
|
||||
this.setState({reason});
|
||||
}
|
||||
|
||||
openDialog(actionType) {
|
||||
const dialogContent = this.getAcceptanceDialog(actionType);
|
||||
this.setState({actionType});
|
||||
this.props.dispatch(setDialogOpenFlag(true));
|
||||
this.props.dispatch(setDialogContent(dialogContent));
|
||||
}
|
||||
|
||||
getAcceptanceDialog(actionType) {
|
||||
return {
|
||||
buttons: [
|
||||
{
|
||||
color: 'success',
|
||||
action: this.acceptDeclineInstallation,
|
||||
name: orderTexts.buttons.SEND,
|
||||
id: 'confirm-acceptance'
|
||||
}, {
|
||||
color: 'secondary',
|
||||
name: orderTexts.buttons.CANCEL,
|
||||
id: 'cancel-acceptance'
|
||||
}
|
||||
],
|
||||
header: orderTexts.labels.ACCEPTANCE_HEADER,
|
||||
TagName: AcceptanceDeclineReason,
|
||||
params: {onEditorChange: this.onEditorChange, actionType}
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
const {idOrder} = this.props.step;
|
||||
this.props.dispatch(fetchCustomerAcceptance(idOrder));
|
||||
}
|
||||
|
||||
render() {
|
||||
const {step} = this.props;
|
||||
const customerAcceptance = this.props.customerAcceptance || null;
|
||||
|
||||
return (
|
||||
<div id="customer-acceptance" className="validate-questionnaire">
|
||||
{
|
||||
customerAcceptance &&
|
||||
<Row>
|
||||
<Col className="aceeptance-message">
|
||||
{this.getAcceptanceMessage(customerAcceptance)} <div className={'status-icon ' + this.getAcceptanceStatusClass(customerAcceptance.customerAccepted, customerAcceptance.daysDiff)}></div>
|
||||
</Col>
|
||||
</Row>
|
||||
}
|
||||
{
|
||||
(customerAcceptance && customerAcceptance.customerAccepted === -1) &&
|
||||
<Row>
|
||||
<Col>{orderTexts.labels.REASON}: {customerAcceptance.customerDeclineReason}</Col>
|
||||
</Row>
|
||||
}
|
||||
<Row className="acceptance-docs">
|
||||
<Col xl="4" lg="5" md="4">
|
||||
<Dropzone className="upload-file-drop-zone"
|
||||
multiple={false}
|
||||
accept=".pdf,.docx,.doc,.xlsx,.xls,.odt,.ods,.jpg,.png,.jpeg"
|
||||
activeClassName="upload-file-accept"
|
||||
onDrop={(acceptedFiles, rejectedFiles)=>{this.uploadFile(step.idOrder, acceptedFiles, rejectedFiles)}}>
|
||||
<h5 className="drop-zone-text">{orderTexts.labels.UPLOAD_ACCEPTANCE_LABEL}</h5>
|
||||
</Dropzone>
|
||||
</Col>
|
||||
<Col xl="4" lg="7" md="8">
|
||||
{
|
||||
(customerAcceptance && customerAcceptance.acceptanceDocuments && customerAcceptance.acceptanceDocuments.length > 0) &&
|
||||
<div>
|
||||
{
|
||||
customerAcceptance.acceptanceDocuments.map(document => <div key={'acceptance-documnet-' + document.idDocument}>
|
||||
<span className="document-link"
|
||||
onClick={() => {this.downloadDocument(document)}}>
|
||||
<i className={'fa fa-file'}></i> {document.documentName} ({document.extension})
|
||||
</span>
|
||||
<span className="document-status">
|
||||
{document.validation} <div className={'status-icon ' + document.validation}></div>
|
||||
</span>
|
||||
</div>)
|
||||
}
|
||||
</div>
|
||||
}
|
||||
{
|
||||
(customerAcceptance && !customerAcceptance.acceptanceDocuments) &&
|
||||
<div>
|
||||
{orderTexts.labels.NO_DOCUMENTS_UPLOADED}
|
||||
</div>
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col className="acceptance-label" xl="12" lg="12" md="12" xs="12">
|
||||
{orderTexts.labels.ACCEPTANCE_LABEL}
|
||||
</Col>
|
||||
<Col lg="7">
|
||||
<Button onClick={()=>{this.openDialog('accept')}}
|
||||
id="acceptance-accept"
|
||||
color="secondary"
|
||||
className="acceptance-button acceptance-accept">{orderTexts.buttons.ACCEPT_INSTALLATION}</Button>
|
||||
<Button onClick={()=>{this.openDialog('decline')}}
|
||||
id="acceptance-decline"
|
||||
color="secondary"
|
||||
className="acceptance-button acceptance-decline">{orderTexts.buttons.DECLINE_INSTALLATION}</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
customerAcceptance: state.processReducer.customerAcceptance
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(CustomerAcceptance);
|
||||
@@ -0,0 +1,54 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Row, Col} from 'reactstrap';
|
||||
import ProcessStep from './ProcessStep.jsx';
|
||||
import {orderTexts} from '../../../../constants/ordersConstants';
|
||||
|
||||
const completedOrdersStatuses = ['production', 'end-of-life'];
|
||||
|
||||
class OrderProcess extends Component {
|
||||
isStepVisible(step) {
|
||||
return (step.status === 'in-progress' || step.status === 'done') && step.isVisibleForCustomer === 1;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {orderProcess, orderStatus} = this.props;
|
||||
const visibleSteps = (orderProcess && orderProcess.steps) ? orderProcess.steps.filter(this.isStepVisible) : [];
|
||||
|
||||
if(orderProcess && completedOrdersStatuses.find((status) => {return status === orderStatus;})) {
|
||||
const processCompleted = {
|
||||
shortDesc: orderTexts.labels.COMPLETED,
|
||||
status: 'done',
|
||||
isVisibleForCustomer: 1,
|
||||
actualDate: visibleSteps[0].actualDate
|
||||
};
|
||||
if(visibleSteps) {
|
||||
visibleSteps.unshift(processCompleted);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="order-process">
|
||||
{
|
||||
(!orderProcess || !orderProcess.steps) &&
|
||||
<Row>
|
||||
<Col xl="12" lg="12" md="12" xs="12">
|
||||
<div className="no-process-info">{orderTexts.labels.WILL_BE_PROCESS}</div>
|
||||
</Col>
|
||||
</Row>
|
||||
}
|
||||
{
|
||||
(orderProcess && orderProcess.steps) &&
|
||||
<Row>
|
||||
<Col xl="12" lg="12" md="12" xs="12" className="order-package-process">
|
||||
{
|
||||
visibleSteps.map((step, index) => <ProcessStep isStepVisible={this.isStepVisible} stepNumber={visibleSteps.length - index} step={step} key={'step-' + step.idProcess + '-' + step.idProcessStep}/>)
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default OrderProcess;
|
||||
@@ -0,0 +1,76 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Row, Col, Container} from 'reactstrap';
|
||||
import WiaasBox from '../../../../mainComponents/box/WiaasBox.jsx';
|
||||
import ValidateQuestionnaire from './ValidateQuestionnaire.jsx';
|
||||
import CustomerAcceptance from './CustomerAcceptance.jsx';
|
||||
|
||||
const stepActions = {
|
||||
'validate-questionnaire' : ValidateQuestionnaire,
|
||||
'customer-acceptance' : CustomerAcceptance
|
||||
}
|
||||
|
||||
class OrderStep extends Component {
|
||||
isActiveStep(status) {
|
||||
return status === 'in-progress' ;
|
||||
}
|
||||
|
||||
getStepTitle(step, stepNumber) {
|
||||
return stepNumber + '. ' + step.shortDesc;
|
||||
}
|
||||
|
||||
getDayFromActual(step) {
|
||||
const date = step.actualDate || step.now;
|
||||
const dateParts = date.split(' ');
|
||||
|
||||
return dateParts[0];
|
||||
}
|
||||
|
||||
getMonthFromActual(step) {
|
||||
const date = step.actualDate || step.now;
|
||||
const dateParts = date.split(' ');
|
||||
const dateParts2 = dateParts[1].split(',');
|
||||
|
||||
return dateParts2[0];
|
||||
}
|
||||
|
||||
render() {
|
||||
const {step, stepNumber, isStepVisible} = this.props;
|
||||
const TagName = step.actionCode !== 'manual' && stepActions[step.actionCode] ? stepActions[step.actionCode] : null;
|
||||
|
||||
return (
|
||||
<Container fluid={true} className="order-step">
|
||||
{
|
||||
isStepVisible(step) &&
|
||||
<Row className="step-layer">
|
||||
<Col xl="1" lg="1" md="2" xs="2" className="step-circle-layer">
|
||||
<div className="step-line"></div>
|
||||
<div className={'step-circle ' + step.status}>
|
||||
{!this.isActiveStep(step.status) &&
|
||||
<span>
|
||||
<div>{this.getDayFromActual(step)}</div>
|
||||
<div>{this.getMonthFromActual(step)}</div>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
</Col>
|
||||
<Col xl="11" lg="11" md="10" xs="10" className="step-box-layer">
|
||||
<WiaasBox isContentVisible={this.isActiveStep(step.status)} className={'step-box'} mainTitle={this.getStepTitle(step, stepNumber)}>
|
||||
{
|
||||
(this.isActiveStep(step.status) && TagName) &&
|
||||
<Col>
|
||||
{
|
||||
(TagName && this.isActiveStep(step.status)) && <TagName step={step}/>
|
||||
}
|
||||
</Col>
|
||||
}
|
||||
</WiaasBox>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
}
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default OrderStep;
|
||||
@@ -0,0 +1,46 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import {fetchCustomerDocuments, fetchValidationComments} from '../../../../actions/orders/processActions';
|
||||
import ValidateQuestionnaireItem from './ValidateQuestionnaireItem.jsx';
|
||||
import '../../style/ValidateQuestionnaire.css';
|
||||
|
||||
class ValidateQuestionnaire extends Component {
|
||||
|
||||
componentDidMount(){
|
||||
const {idOrder, idProcessStep} = this.props.step;
|
||||
this.props.dispatch(fetchCustomerDocuments(idOrder, 'orderQuestionaire'));
|
||||
this.props.dispatch(fetchValidationComments(idOrder, idProcessStep, 'invalidQuestionnaireComment'));
|
||||
}
|
||||
|
||||
findById(orderPackage, idOrderPackagePair){
|
||||
const idPackage = idOrderPackagePair.split('-')[1];
|
||||
return orderPackage.idPackage === parseInt(idPackage, 10);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {customerDocuments, validationComments, orderPackages} = this.props;
|
||||
|
||||
return (
|
||||
<div id="validate-questionnaire" className="validate-questionnaire">
|
||||
{
|
||||
customerDocuments &&
|
||||
Object.keys(customerDocuments).map((idOrderPackagePair) =>
|
||||
<ValidateQuestionnaireItem
|
||||
customerDocuments={customerDocuments[idOrderPackagePair]}
|
||||
validationComments={validationComments && validationComments[idOrderPackagePair] ? validationComments[idOrderPackagePair] : []}
|
||||
orderPackage={orderPackages.find((orderPackage)=>{ return this.findById(orderPackage, idOrderPackagePair)})}
|
||||
key={'validate-questionnaire-' + idOrderPackagePair}/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
customerDocuments: state.processReducer.customerDocuments,
|
||||
validationComments: state.processReducer.validationComments,
|
||||
orderPackages: state.processReducer.orderInfo.packages
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(ValidateQuestionnaire);
|
||||
@@ -0,0 +1,99 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import Dropzone from 'react-dropzone';
|
||||
import {Row, Col} from 'reactstrap';
|
||||
import {reUploadOrderDocument, badFile} from '../../../../actions/orders/processActions';
|
||||
import {API_SERVER} from '../../../../config';
|
||||
import FileDownloader from '../../../../helpers/FileDownloader';
|
||||
import {orderTexts} from '../../../../constants/ordersConstants';
|
||||
|
||||
const fileHandler = new FileDownloader();
|
||||
|
||||
class ValidateQuestionnaireItem 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);
|
||||
}
|
||||
|
||||
uploadFile(idPackage, idOrder, idDocument,acceptedFiles, rejectedFiles) {
|
||||
if(acceptedFiles && acceptedFiles.length){
|
||||
const file = acceptedFiles[0];
|
||||
this.props.dispatch(reUploadOrderDocument(idPackage, idOrder, idDocument, file));
|
||||
}
|
||||
|
||||
if(rejectedFiles && rejectedFiles.length) {
|
||||
this.props.dispatch(badFile());
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {customerDocuments, validationComments, orderPackage} = this.props;
|
||||
|
||||
return (
|
||||
<div id="validate-questionnaire" className="validate-questionnaire">
|
||||
{
|
||||
customerDocuments &&
|
||||
<div>
|
||||
{orderPackage.packageName}
|
||||
{
|
||||
customerDocuments.map(document => <div key={'package-document-' + document.idDocument}>
|
||||
{
|
||||
document.validation === 'invalid'
|
||||
? <div className="package-document">
|
||||
<Row>
|
||||
<Col xl="7" lg="8">
|
||||
<div>
|
||||
<span className="document-link"
|
||||
onClick={() => {this.downloadDocument(document)}}>
|
||||
<i className={'fa fa-file'}></i> {document.documentName} ({document.extension}) {' '}
|
||||
</span>
|
||||
<span className="document-status">
|
||||
{document.validation.replace(/-/g,' ')} <div className={'status-icon ' + document.validation}></div>
|
||||
</span>
|
||||
</div>
|
||||
{
|
||||
(validationComments && validationComments.length > 0) &&
|
||||
<div>
|
||||
{validationComments.map((comment, key) => <div key={'step-comment-' + document.idDocument + '-' + key} className="step-comment">
|
||||
<div>{comment.user} - {comment.addDate}</div>
|
||||
<div>{comment.comment}</div>
|
||||
</div>)}
|
||||
</div>
|
||||
}
|
||||
</Col>
|
||||
<Col xl="5">
|
||||
<Dropzone className="upload-file-drop-zone"
|
||||
multiple={false}
|
||||
accept=".pdf,.docx,.doc,.xlsx,.xls,.odt,.ods"
|
||||
activeClassName="upload-file-accept"
|
||||
onDrop={(acceptedFiles, rejectedFiles)=>{this.uploadFile(document.idPackage, document.idOrder, document.idDocument, acceptedFiles, rejectedFiles)}}>
|
||||
<h5 className="drop-zone-text">{orderTexts.labels.SELECT_OR_DROP}</h5>
|
||||
</Dropzone>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
: <div className="package-document">
|
||||
<Row>
|
||||
<Col>
|
||||
<span className="document-link"
|
||||
onClick={() => {this.downloadDocument(document)}}>
|
||||
<i className={'fa fa-file'}></i> {document.documentName} ({document.extension}) {' '}
|
||||
</span>
|
||||
<span className="document-status">
|
||||
{document.validation.replace(/-/g,' ')} <div className={'status-icon ' + document.validation}></div>
|
||||
</span>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
}
|
||||
</div>)
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default connect()(ValidateQuestionnaireItem);
|
||||
66
frontend/src/containers/orders/style/CustomerAcceptance.scss
Normal file
66
frontend/src/containers/orders/style/CustomerAcceptance.scss
Normal file
@@ -0,0 +1,66 @@
|
||||
@import '../../../styleConstants.scss';
|
||||
|
||||
#customer-acceptance {
|
||||
padding: 1rem 0;
|
||||
|
||||
.waiting {
|
||||
background: $pending-status-color;
|
||||
}
|
||||
|
||||
.accepted {
|
||||
background: $validated-status-color;
|
||||
}
|
||||
|
||||
.declined {
|
||||
background: $declined-stattus-color;
|
||||
}
|
||||
|
||||
.danger {
|
||||
background: $danger;
|
||||
}
|
||||
|
||||
.warning {
|
||||
background: $warning;
|
||||
}
|
||||
|
||||
.acceptance-button {
|
||||
margin-top: 1rem;
|
||||
cursor: pointer;
|
||||
background: $whiteColor;
|
||||
}
|
||||
|
||||
.acceptance-accept {
|
||||
color: $production-status-color;
|
||||
}
|
||||
|
||||
.acceptance-decline {
|
||||
margin-left: 0.5rem;
|
||||
color: $canceled-status-color;
|
||||
|
||||
.package-document {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.acceptance-docs {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.acceptance-label {
|
||||
margin-top: 1rem;
|
||||
font-weight: $font-weight;
|
||||
}
|
||||
|
||||
@media all and (max-width: 768px) {
|
||||
|
||||
.aceeptance-message {
|
||||
font-size: $font-size-small
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width: 480px) {
|
||||
.acceptance-decline {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
112
frontend/src/containers/orders/style/InstallationScheduling.scss
Normal file
112
frontend/src/containers/orders/style/InstallationScheduling.scss
Normal file
@@ -0,0 +1,112 @@
|
||||
@import '../../../styleConstants.scss';
|
||||
|
||||
.installation-scheduling-dates-container {
|
||||
padding-bottom: 1rem;
|
||||
|
||||
.confirmation-dates-buttons {
|
||||
float: right;
|
||||
|
||||
.install-btn-accept {
|
||||
color: $production-status-color;
|
||||
}
|
||||
|
||||
.install-btn-decline {
|
||||
color: $canceled-status-color;
|
||||
}
|
||||
|
||||
.install-btn-remove {
|
||||
color: $warm-grey;
|
||||
}
|
||||
}
|
||||
|
||||
.installation-button {
|
||||
width: 5rem;
|
||||
margin-left: 1rem;
|
||||
height: 2rem;
|
||||
font-size: $font-size-small;
|
||||
cursor: pointer;
|
||||
background-color: $whiteColor;
|
||||
font-weight: $font-weight;
|
||||
}
|
||||
|
||||
.dates-info-btn {
|
||||
margin-left: 1rem;
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.dates-info-popover {
|
||||
max-width: 50rem;
|
||||
}
|
||||
|
||||
.status-icon-installation-dates {
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
.installation-date-proposed {
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
.installation-scheduling-dates-container:hover {
|
||||
background-color: $hoverColor;
|
||||
}
|
||||
|
||||
.dates-info-popover {
|
||||
.react-datepicker {
|
||||
font-family: $ProximaNova-font;
|
||||
border: none;
|
||||
border-radius: unset;
|
||||
}
|
||||
}
|
||||
|
||||
#installation-scheduler-container {
|
||||
.document-link {
|
||||
cursor: pointer;
|
||||
word-wrap: break-word;
|
||||
font-size: $font-size-small;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.set-installation-dates {
|
||||
background: $whiteColor;
|
||||
}
|
||||
|
||||
.check-installation-dates {
|
||||
cursor: pointer;
|
||||
color: $blueColor;
|
||||
font-weight: $font-weight;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
padding-right: 0.5rem;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.install-date-text {
|
||||
display: inline-block;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
|
||||
.order-package-row {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.package-installation-row {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.scheduled-date-btn {
|
||||
margin-left: 0.7rem;
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.scheduled-date-popover {
|
||||
max-width: 50rem;
|
||||
}
|
||||
128
frontend/src/containers/orders/style/Orders.scss
Normal file
128
frontend/src/containers/orders/style/Orders.scss
Normal file
@@ -0,0 +1,128 @@
|
||||
@import '../../../styleConstants.scss';
|
||||
|
||||
$borderWidth: 3px;
|
||||
|
||||
#orders-list-container {
|
||||
.orders-tab {
|
||||
cursor: pointer;
|
||||
}
|
||||
.order-central-row {
|
||||
border-radius: 1.5px;
|
||||
}
|
||||
|
||||
.order-border-open {
|
||||
border-left: $borderWidth $open-status-color solid;
|
||||
}
|
||||
|
||||
.order-border-in-progress {
|
||||
border-left: $borderWidth $in-progress-status-color solid;
|
||||
}
|
||||
|
||||
.order-border-production {
|
||||
border-left: $borderWidth $production-status-color solid;
|
||||
}
|
||||
|
||||
.order-border-end-of-life {
|
||||
border-left: $borderWidth $end-of-life-status-color solid;
|
||||
}
|
||||
|
||||
.order-border-canceled {
|
||||
border-left: $borderWidth $canceled-status-color solid;
|
||||
}
|
||||
|
||||
.cl-photo{
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.order-number {
|
||||
display: inline-block;
|
||||
padding-left: 1rem;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.package-photo {
|
||||
padding-left: 1rem;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.package-info-col {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.actions-button {
|
||||
background-color: $whiteColor;
|
||||
color: $darkGreyColor;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.actions-button:hover{
|
||||
background: rgba(113, 194, 191, 0.5);
|
||||
}
|
||||
|
||||
.status-icon {
|
||||
width: $font-size-xsmal;
|
||||
height: $font-size-xsmal;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.open {
|
||||
background: $open-status-color;
|
||||
}
|
||||
|
||||
.in-progress {
|
||||
background: $in-progress-status-color;
|
||||
}
|
||||
|
||||
.production {
|
||||
background: $production-status-color;
|
||||
}
|
||||
|
||||
.order-item-cl {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.cl-contact-name {
|
||||
font-weight: $font-weight;
|
||||
color: $darkGreyColor;
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
|
||||
.cl-name {
|
||||
font-weight: unset;
|
||||
font-size: $font-size-msmall;
|
||||
color: $warmGreyColor;
|
||||
}
|
||||
|
||||
.cl-details {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.package-name {
|
||||
display: inline-block;
|
||||
padding-left: 1rem;
|
||||
bottom: 0;
|
||||
font-size: $font-size-small;
|
||||
font-weight: $font-weight;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.order-details-container {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.toggle-view-packages {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.actions-link {
|
||||
color: $darkGreyColor;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.actions-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
3
frontend/src/containers/orders/style/OrdersList.scss
Normal file
3
frontend/src/containers/orders/style/OrdersList.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
.view-all-orders-text {
|
||||
padding-left: 0.3rem;
|
||||
}
|
||||
366
frontend/src/containers/orders/style/ProcessContainer.scss
Normal file
366
frontend/src/containers/orders/style/ProcessContainer.scss
Normal file
@@ -0,0 +1,366 @@
|
||||
@import '../../../styleConstants.scss';
|
||||
$border-width: 5px;
|
||||
$link-line-height: 1.5rem;
|
||||
|
||||
#order-info {
|
||||
.subtitle {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.info-color {
|
||||
margin-top: 0.2rem;
|
||||
padding-left: 0.2rem;
|
||||
}
|
||||
|
||||
.no-process {
|
||||
background: $open-status-color;
|
||||
}
|
||||
|
||||
.processing {
|
||||
border-left: $border-width $processing-status-color solid;
|
||||
}
|
||||
|
||||
.canceled {
|
||||
border-left: $border-width $canceled-status-color solid;
|
||||
}
|
||||
|
||||
.production {
|
||||
border-left: $border-width $production-status-color solid;
|
||||
}
|
||||
|
||||
.end-of-life {
|
||||
border-left: $border-width $end-of-life-status-color solid;
|
||||
}
|
||||
|
||||
.wiaas-box-container {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.components-link {
|
||||
position: relative;
|
||||
height: $link-line-height;
|
||||
|
||||
.link-line {
|
||||
position: absolute;
|
||||
background: $borderColor;
|
||||
width: 3px;
|
||||
top: 0;
|
||||
left: 49%;
|
||||
height: $link-line-height;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.package-name-link {
|
||||
font-size: $font-size-big;
|
||||
font-weight: $font-weight;
|
||||
text-align: left;
|
||||
color: $title-color;
|
||||
}
|
||||
}
|
||||
|
||||
.order-process{
|
||||
|
||||
.no-process-info {
|
||||
background: $whiteColor;
|
||||
padding: 1rem;
|
||||
font-size: $font-size-normal;
|
||||
font-weight: $font-weight;
|
||||
}
|
||||
}
|
||||
|
||||
.order-step{
|
||||
.wiaas-box-container {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.step-circle-layer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.step-circle {
|
||||
z-index: 1;
|
||||
margin-top: $link-line-height;
|
||||
position: relative;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
color: $whiteColor;
|
||||
line-height: 1rem;
|
||||
padding: 0.5rem;
|
||||
display: inline-block;
|
||||
font-weight: $font-weight;
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
|
||||
.step-line{
|
||||
position: absolute;
|
||||
background: $borderColor;
|
||||
width: 2%;
|
||||
top: 0;
|
||||
left: 49%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.order-step:last-child .step-line{
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
.step-box-layer {
|
||||
margin-top: $link-line-height;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.step-box {
|
||||
background: $whiteColor;
|
||||
border-radius: 1.5px;
|
||||
|
||||
.wiaas-main-title {
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
}
|
||||
|
||||
.end-of-life {
|
||||
background: $end-of-life-status-color;
|
||||
}
|
||||
|
||||
.canceled {
|
||||
background: $canceled-status-color;
|
||||
}
|
||||
|
||||
.production {
|
||||
background: $production-status-color;
|
||||
}
|
||||
|
||||
.open {
|
||||
background: $open-status-color;
|
||||
}
|
||||
|
||||
.done {
|
||||
background: $done-status-color;
|
||||
}
|
||||
|
||||
.in-progress {
|
||||
background: $in-progress-status-color;
|
||||
}
|
||||
|
||||
.inactive {
|
||||
background: $inactive-status-color;
|
||||
}
|
||||
|
||||
.step-comment {
|
||||
margin-top: 1rem;
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
|
||||
.new-comment-button {
|
||||
background-color: $whiteColor;
|
||||
color: $darkGreyColor;
|
||||
font-size: $font-size-small;
|
||||
cursor: pointer;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.support-mail-button {
|
||||
background-color: $whiteColor;
|
||||
color: $darkGreyColor;
|
||||
font-size: $font-size-small;
|
||||
cursor: pointer;
|
||||
margin-top: 0.5rem;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.upload-file-drop-zone {
|
||||
width: 100%;
|
||||
border: 3px dashed $borderColor;
|
||||
height: 10rem;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.upload-file-accept {
|
||||
border: 3px dashed $greenColor;
|
||||
background: rgba(52, 195, 136, 0.1);
|
||||
}
|
||||
|
||||
.upload-file-drop-zone:hover{
|
||||
border: 3px dashed $greenColor;
|
||||
background: rgba(52, 195, 136, 0.1);
|
||||
}
|
||||
|
||||
.status-icon {
|
||||
width: $font-size-xsmal;
|
||||
height: $font-size-xsmal;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.drop-zone-text {
|
||||
text-align: center;
|
||||
padding: 4rem 0;
|
||||
}
|
||||
|
||||
.document-link {
|
||||
cursor: pointer;
|
||||
word-wrap: break-word;
|
||||
|
||||
.step-comment {
|
||||
padding: 0.5rem 1rem 1rem;
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
}
|
||||
|
||||
.order-package-info {
|
||||
background: $whiteColor;
|
||||
padding-bottom: 1rem;
|
||||
|
||||
.document-link {
|
||||
cursor: pointer;
|
||||
word-wrap: break-word;
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
|
||||
.price-info-btn {
|
||||
margin-left: 1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.price-info-popover {
|
||||
max-width: 50rem;
|
||||
}
|
||||
|
||||
.link-to-docs{
|
||||
cursor: pointer;
|
||||
color: $blueColor;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
#order-info-description {
|
||||
background: $whiteColor;
|
||||
padding-bottom: 1rem;
|
||||
|
||||
.terms-link {
|
||||
cursor: pointer;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.terms-label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.installation-date-per-package {
|
||||
font-weight: $font-weight;
|
||||
}
|
||||
}
|
||||
|
||||
#order-comments {
|
||||
background: $whiteColor;
|
||||
|
||||
.order-coments-body{
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.order-comment {
|
||||
margin-top: 0.5rem;
|
||||
font-size: $font-size-small;
|
||||
background: rgba(43, 98, 121, 0.2);
|
||||
padding: 0.5rem;
|
||||
border-radius: $box-radius;
|
||||
}
|
||||
|
||||
.mine {
|
||||
background: rgba(113, 194, 191, 0.2);
|
||||
}
|
||||
|
||||
.order-comment-header {
|
||||
font-weight: $font-weight;
|
||||
}
|
||||
}
|
||||
|
||||
.confirmation-proposed {
|
||||
color: $pending-status-color;
|
||||
}
|
||||
|
||||
.confirmation-accepted {
|
||||
color: $done-status-color;
|
||||
}
|
||||
|
||||
.confirmation-declined {
|
||||
color: $canceled-status-color;
|
||||
}
|
||||
|
||||
.confirmation-canceled {
|
||||
color: $invalid-status-color;
|
||||
}
|
||||
|
||||
.confirmation-invalid {
|
||||
color: $invalid-status-color;
|
||||
}
|
||||
|
||||
#order-documents{
|
||||
.document-link-big {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
padding: 1rem;
|
||||
margin-bottom: 3px;
|
||||
text-align: center;
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
|
||||
.document-link-big a {
|
||||
color: $blueColor;
|
||||
}
|
||||
|
||||
.document-link-big:hover {
|
||||
margin-bottom: 0;
|
||||
color: $title-color;
|
||||
border-bottom: $blueColor 3px solid;
|
||||
}
|
||||
}
|
||||
|
||||
#send-support-mail-container {
|
||||
.support-details {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.package-name {
|
||||
font-weight: $font-weight;
|
||||
}
|
||||
|
||||
.order-package-details {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
#my-support-mail-text {
|
||||
width: 50rem;
|
||||
height: 10rem;
|
||||
}
|
||||
|
||||
@media all and (max-width: 1032px) {
|
||||
#my-support-mail-text {
|
||||
width: 22rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width: 768px) {
|
||||
|
||||
.drop-zone-text {
|
||||
text-align: center;
|
||||
padding: 4rem 0;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.document-link {
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
|
||||
#my-support-mail-text {
|
||||
width: 16rem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
@import '../../../styleConstants.scss';
|
||||
|
||||
.process-nav {
|
||||
|
||||
|
||||
.process-menu {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.process-nav-div {
|
||||
display: inline-block;
|
||||
margin-left: 1rem;
|
||||
cursor: pointer;
|
||||
font-weight: $font-weight;
|
||||
color: $blueColor;
|
||||
}
|
||||
|
||||
.selected-nav {
|
||||
border-bottom: $blueColor 3px solid;
|
||||
color: $title-color;
|
||||
}
|
||||
|
||||
.process-nav-div:hover {
|
||||
border-bottom: $blueColor 3px solid;
|
||||
}
|
||||
|
||||
.status-layer{
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
border-radius: 3px;
|
||||
color: $whiteColor;
|
||||
padding: 0.2rem 1rem;
|
||||
font-size: $font-size-xsmal;
|
||||
margin-left: 0.7rem;
|
||||
font-weight: $font-weight;
|
||||
}
|
||||
|
||||
.schedule-active {
|
||||
cursor: pointer;
|
||||
background-color: $whiteColor;
|
||||
color: $darkGreyColor;
|
||||
opacity: 0.8;
|
||||
border: 0.1rem $border-grey solid;
|
||||
display: inline-block;
|
||||
border-radius: $box-radius;
|
||||
font-weight: $font-weight;
|
||||
}
|
||||
|
||||
.schedule-inactive {
|
||||
cursor: no-drop;
|
||||
background-color: $whiteColor;
|
||||
color: $darkGreyColor;
|
||||
opacity: 0.4;
|
||||
border: 0.1rem $border-grey solid;
|
||||
display: inline-block;
|
||||
border-radius: $box-radius;
|
||||
font-weight: $font-weight;
|
||||
}
|
||||
|
||||
@media all and (max-width: 576px) {
|
||||
|
||||
.process-menu {
|
||||
text-align: left;
|
||||
}
|
||||
.process-nav-div {
|
||||
margin-left: 0;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
@import '../../../styleConstants.scss';
|
||||
|
||||
#validate-questionnaire {
|
||||
padding: 1rem 0;
|
||||
|
||||
.invalid {
|
||||
background: $invalid-status-color;
|
||||
}
|
||||
|
||||
.not-validated {
|
||||
background: $pending-status-color;
|
||||
}
|
||||
|
||||
.validated {
|
||||
background: $validated-status-color;
|
||||
}
|
||||
|
||||
.package-document {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.document-status {
|
||||
font-weight: $font-weight;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user