801 lines
22 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from "react";
import { SpinnerCircular } from "spinners-react";
import moment from "moment";
import pluralize from 'pluralize-ru';
import numeral from "numeral";
import DateInput from "../../../../../components/DatePicker";
import { getContractGraphicChangeOptions, getContractGraphicChangeCalculate } from "../../../../../actions";
class PaymentDate extends React.Component
{
constructor(props)
{
super(props);
this.state = {
value: null,
min: null,
max: null,
help: false,
}
}
componentDidMount()
{
const { option, onOption } = this.props;
this.setState({
value: moment(option.value).toDate(),
min: moment(option.from).toDate(),
max: moment(option.to).toDate(),
}, () =>
{
onOption(this.state.value);
});
}
_handle_onChange = (value) =>
{
const { onOption } = this.props;
this.setState({ value }, () =>
{
onOption(value);
});
}
_handle_onMobileHelp = () =>
{
if(window.innerWidth < 768)
{
this.setState({ help: this.state.help ? false : true });
}
}
render()
{
const { option } = this.props;
const { value, min, max } = this.state;
return (
<div className="form_field">
<label>Дата платежа:</label>
<DateInput
placeholder=""
value={ value }
min={ min }
max={ max }
id={"date_to"}
onChange={ this._handle_onChange }
disabled={ option.disable ? true : false }
plain={ true }
/>
</div>
)
}
}
class FixLastPayment extends React.Component
{
constructor(props)
{
super(props);
this.state = {
value: false,
help: false,
};
}
componentDidMount()
{
const { option, onOption } = this.props;
this.setState({
value: option.value,
}, () =>
{
onOption(this.state.value);
});
}
_handle_onChange = () =>
{
const { onOption } = this.props;
this.setState({ value: this.state.value ? false : true }, () =>
{
onOption(this.state.value);
});
}
_handle_onMobileHelp = () =>
{
if(window.innerWidth < 768)
{
this.setState({ help: this.state.help ? false : true });
}
}
render()
{
const { option } = this.props;
const { value, help } = this.state;
return (
<div className="form_field">
<input type="checkbox" hidden id="fix_pay" name="fix_pay" checked={ value } disabled={ option.disable ? true : false } onChange={ this._handle_onChange } style={ option.disable ? { opacity: 0.5 } : {} } />
<label htmlFor="fix_pay" style={ option.disable ? { opacity: 0.5 } : {} }>
Не менять сумму последнего платежа
</label>
{ option.information !== undefined && option.information !== null && (
<div className="help_tooltip">
<div className="help_icon" onClick={ () => this._handle_onMobileHelp() }>
<svg width={ 24 } height={ 24 } fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18Z" stroke="#8E94A7" strokeWidth={ 2 } strokeLinecap="round" strokeLinejoin="round" />
<path d="M11.25 11.25H12v5.25h.75" stroke="#8E94A7" strokeWidth={ 2 } strokeLinecap="round" strokeLinejoin="round" />
<path d="M12 9a1.125 1.125 0 1 0 0-2.25A1.125 1.125 0 0 0 12 9Z" fill="#8E94A7" />
</svg>
</div>
<div className={`help_content ${ help && "opened" }`}>
<div>
<p dangerouslySetInnerHTML={{ __html: option.information }}/>
<p className="button" onClick={ () => this._handle_onMobileHelp() }>Закрыть</p>
</div>
</div>
</div>
) }
</div>
)
}
}
class DateOffestType extends React.Component
{
constructor(props)
{
super(props);
this.state = {
value: null,
}
}
componentDidMount()
{
const { option, onOption } = this.props;
this.setState({
value: parseInt(option.value, 10),
}, () =>
{
onOption(this.state.value);
});
}
_handle_onChange = (value) =>
{
const { onOption } = this.props;
this.setState({ value: parseInt(value, 10) }, () =>
{
onOption(this.state.value);
});
}
render()
{
const { option } = this.props;
const { value } = this.state;
return (
<div className="form_field">
<label>Тип каникул:</label>
<div className="form_field">
{ (!option.disable || (option.disable && value === 100000001)) && (
<>
<input type="radio" hidden id="weeekend_type_1" name="weeekend_type" checked={ value === 100000001 ? true : false } disabled={ option.disable ? true : false } onChange={ () => this._handle_onChange(100000001) }/>
<label htmlFor="weeekend_type_1">С увеличением срока</label>
</>
) }
</div>
<div className="form_field">
{ (!option.disable || (option.disable && value === 100000000)) && (
<>
<input type="radio" hidden id="weeekend_type_2" name="weeekend_type" checked={ value === 100000000 ? true : false } disabled={ option.disable ? true : false } onChange={ () => this._handle_onChange(100000000) }/>
<label htmlFor="weeekend_type_2">Без изменения срока</label>
</>
) }
</div>
</div>
)
}
}
class PeriodSelector extends React.Component
{
constructor(props)
{
super(props);
this.state = {
value: null,
periods: [],
}
}
componentDidMount()
{
const { option, onOption } = this.props;
const periods = [];
if(option.min !== undefined && option.min !== null)
{
for(let i = parseInt(option.min, 10); i <= parseInt(option.max, 10); i++)
{
periods.push(i);
}
this.setState({
value: periods[0], periods
}, () =>
{
onOption(this.state.value);
});
}
}
_handle_onChange = (event) =>
{
const { onOption } = this.props;
this.setState({ value: parseInt(event.target.value, 10) }, () =>
{
onOption(this.state.value);
});
}
render()
{
const { option } = this.props;
const { value, periods } = this.state;
if(value !== null)
{
return (
<div className="form_field" style={ option.disable ? { opacity: 0.5 } : {} }>
<label>Увеличить срок договора на:</label>
<select value={ value } onChange={ this._handle_onChange } disabled={ option.disable ? true : false }>
{ periods.map((period, index) => (
<option key={ index } value={ period }>{ index + 1 } { pluralize( index + 1, 'месяца', 'месяц', 'месяца', 'месяцев') } ({ period } { pluralize( period, 'платежа', 'платеж', 'платежа', 'платежей') })</option>
)) }
</select>
</div>
)
}
return null;
}
}
class SumSelector extends React.Component
{
constructor(props)
{
super(props);
this.state = {
value: "",
min: null,
max: null,
help: false,
}
}
componentDidMount()
{
const { option, onOption } = this.props;
this.setState({
value: option.value !== null ? option.value : option.min,
min: option.min,
max: option.max,
}, () =>
{
onOption(this.state.value, false);
});
}
_handle_onChange = (event) =>
{
const { onOption } = this.props;
const { min, max } = this.state;
const value = parseFloat(event.target.value.replace(',','.').replace(/[^\d,.]/mg, ''));
if(value >= min && value <= max && !isNaN(value))
{
this.setState({ value: value }, () =>
{
onOption(this.state.value, false);
});
}
else
{
onOption(this.state.value, true);
}
}
_handle_onKeyDown = (event) =>
{
if(event.keyCode === 13)
{
event.preventDefault();
this.props.onSubmit(event);
}
}
_handle_onMin = () =>
{
const { onOption } = this.props;
const { min } = this.state;
const value = parseFloat(min).toFixed(2);
this.setState({ value }, () =>
{
onOption(value, false);
});
}
_handle_onMax = () =>
{
const { onOption } = this.props;
const { max } = this.state;
const value = parseFloat(max).toFixed(2);
this.setState({ value }, () =>
{
onOption(value, false);
});
}
_handle_onMobileHelp = () =>
{
if(window.innerWidth < 768)
{
this.setState({ help: this.state.help ? false : true });
}
}
render()
{
const { option } = this.props;
const { value, min, max, help } = this.state;
return (
<div className="form_field">
<label style={ option.disable ? { opacity: 0.5 } : {} }>Изменить сумму платежа</label>
<div className="input_with_notes" style={ option.disable ? { opacity: 0.5 } : {} }>
<input type="number" placeholder="Укажите сумму" defaultValue={ value } disabled={ option.disable ? true : false } onChange={ this._handle_onChange } onKeyDown={ this._handle_onKeyDown }/>
<span className="interactive" style={{ textDecoration: "underline" }} onClick={ this._handle_onMin }>от { numeral(min).format(' ., ') }&nbsp;</span>
<span className="interactive" style={{ textDecoration: "underline" }} onClick={ this._handle_onMax }>до { numeral(max).format(' ., ') }&nbsp;</span>
</div>
{ option.information !== undefined && option.information !== null && (
<div className="help_tooltip">
<div className="help_icon" onClick={ () => this._handle_onMobileHelp() }>
<svg width={ 24 } height={ 24 } fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18Z" stroke="#8E94A7" strokeWidth={ 2 } strokeLinecap="round" strokeLinejoin="round" />
<path d="M11.25 11.25H12v5.25h.75" stroke="#8E94A7" strokeWidth={ 2 } strokeLinecap="round" strokeLinejoin="round" />
<path d="M12 9a1.125 1.125 0 1 0 0-2.25A1.125 1.125 0 0 0 12 9Z" fill="#8E94A7" />
</svg>
</div>
<div className={`help_content ${ help && "opened" }`}>
<div>
<p dangerouslySetInnerHTML={{ __html: option.information }}/>
<p className="button" onClick={ () => this._handle_onMobileHelp() }>Закрыть</p>
</div>
</div>
</div>
) }
</div>
)
}
}
class InsurancePriceSelector extends React.Component
{
constructor(props)
{
super(props);
this.state = {
value: "",
min: null,
max: null,
help: false,
}
}
componentDidMount()
{
const { option, onOption } = this.props;
this.setState({
value: option.min,
min: option.min,
max: option.max,
}, () =>
{
onOption(this.state.value, false);
});
}
_handle_onChange = (event) =>
{
const { option, onOption } = this.props;
const { min, max } = this.state;
//if(option.disable)
//{
// //console.log("////", option.disable);
// this.setState({ value: this.state.value });
//}
//else
//{
const value = parseFloat(event.target.value.replace(',','.').replace(/[^\d,.]/mg, ''));
if(value >= min && value <= max && !isNaN(value))
{
this.setState({ value: value }, () =>
{
onOption(this.state.value, false);
});
}
else
{
onOption(this.state.value, true);
}
//}
}
_handle_onKeyDown = (event) =>
{
if(event.keyCode === 13)
{
event.preventDefault();
this.props.onSubmit(event);
}
}
_handle_onMin = () =>
{
const { min } = this.state;
this.setState({ value: min });
}
_handle_onMax = () =>
{
const { max } = this.state;
this.setState({ value: max });
}
_handle_onMobileHelp = () =>
{
if(window.innerWidth < 768)
{
this.setState({ help: this.state.help ? false : true });
}
}
render()
{
const { option } = this.props;
const { value, min, max, help } = this.state;
return (
<div className="form_field">
<label>Премия по полису КАСКО:</label>
<div className="input_with_notes">
{ option.disable ? (
<>{ numeral(value).format(' ., ') }&nbsp;</>
) : (
<>
<input type="number" placeholder="Укажите сумму" defaultValue={ value } disabled={ option.disable ? true : false } onChange={ this._handle_onChange } onKeyDown={ this._handle_onKeyDown }/>
<span className="interactive" style={{ textDecoration: "underline" }} onClick={ this._handle_onMin }>от { numeral(min).format(' ., ') }&nbsp;</span>
<span className="interactive" style={{ textDecoration: "underline" }} onClick={ this._handle_onMax }>до { numeral(max).format(' ., ') }&nbsp;</span>
</>
) }
</div>
{ option.information !== undefined && option.information !== null && (
<div className="help_tooltip">
<div className="help_icon" onClick={ () => this._handle_onMobileHelp() }>
<svg width={ 24 } height={ 24 } fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18Z" stroke="#8E94A7" strokeWidth={ 2 } strokeLinecap="round" strokeLinejoin="round" />
<path d="M11.25 11.25H12v5.25h.75" stroke="#8E94A7" strokeWidth={ 2 } strokeLinecap="round" strokeLinejoin="round" />
<path d="M12 9a1.125 1.125 0 1 0 0-2.25A1.125 1.125 0 0 0 12 9Z" fill="#8E94A7" />
</svg>
</div>
<div className={`help_content ${ help && "opened" }`}>
<div>
<p dangerouslySetInnerHTML={{ __html: option.information }}/>
<p className="button" onClick={ () => this._handle_onMobileHelp() }>Закрыть</p>
</div>
</div>
</div>
) }
</div>
)
}
}
class InsuranceDateFromSelector extends React.Component
{
constructor(props)
{
super(props);
this.state = {
value: null,
min: null,
max: null,
}
}
componentDidMount()
{
const { option, onOption } = this.props;
this.setState({
value: moment(option.value !== null ? option.value : option.from).toDate(),
min: moment(option.from).toDate(),
max: moment(option.to).toDate(),
}, () =>
{
onOption(this.state.value);
});
}
_handle_onChange = (value) =>
{
const { onOption } = this.props;
this.setState({ value }, () =>
{
onOption(value);
});
}
render()
{
const { option } = this.props;
const { value, min, max } = this.state;
return (
<div className="form_field">
<label>Дата очередного периода по КАСКО:</label>
<DateInput
placeholder=""
value={ value }
min={ min }
max={ max }
id={"date_to"}
onChange={ this._handle_onChange }
disabled={ option.disable ? true : false }
plain={ true }
/>
</div>
)
}
}
export default class Options extends React.Component
{
constructor(props)
{
super(props);
this.state = {
loading: true,
sending: false,
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
number_paydate: null,
period_new: null,
fix_last_payment_available: false,
date_offset_type: null,
sum: null,
insurance_price_result: null,
datefrom: null,
errors: {},
};
}
componentDidMount()
{
const { dispatch, number, variants } = this.props;
const varianst_for_options = {};
for(let i in variants.types)
{
if(variants.types[i].value)
{
varianst_for_options[variants.types[i].name] = true;
}
}
getContractGraphicChangeOptions({ dispatch, number, variants: varianst_for_options })
.then(() =>
{
this.setState({ loading: false });
})
.catch(() =>
{
});
}
_handle_onBack = (event) =>
{
event.preventDefault();
this.props.onVariants();
}
_handle_onCalculate = (event) =>
{
event.preventDefault();
event.stopPropagation();
const { sending, number_paydate, period_new, fix_last_payment_available, date_offset_type, sum, insurance_price_result, datefrom, } = this.state;
const { number, options, variants, onCalculate } = this.props;
if(!sending)
{
this.setState({ sending: true, }, () =>
{
//console.log("_handle_onCalculate ?");
const selected = {
number_planpayment: options.number_planpayment.value,
};
if(number_paydate !== null) { selected.number_paydate = moment(number_paydate).format("YYYY-MM-DD 00:00:00"); }
if(period_new !== null) { selected.period_new = period_new; }
if(fix_last_payment_available !== null) { selected.fix_last_payment_available = fix_last_payment_available; }
if(date_offset_type !== null) { selected.date_offset_type = date_offset_type; }
if(sum !== null) { selected.sum = sum; }
if(insurance_price_result !== null) { selected.insurance_price_result = insurance_price_result; }
//if(early_redemption_change !== null) { selected.early_redemption_change = early_redemption_change; }
if(datefrom !== null) { selected.datefrom = moment(datefrom).format("YYYY-MM-DD 00:00:00"); }
const v = {};
for(let i in variants.types) { v[ variants.types[i].name ] = variants.types[i].value; }
const payload = {
...{ contract_number: number },
...v,
...selected
};
getContractGraphicChangeCalculate(payload)
.then((calculation) =>
{
onCalculate(calculation.addcontract_number);
})
.catch(() =>
{
this.setState({ sending: false, }, () =>
{
alert("К сожалению, при расчёте возникла ошибка.\n\nДля расчёта вариантов изменения графика обратитесь, пожалуйста, в Службу клиентского сервиса по адресу электронной почты client@evoleasing.ru или по телефону Горячей линии 8 800 333 75 75.");
});
});
});
}
}
_handle_onPaymentDateChange = (date) =>
{
this.setState({ number_paydate: date });
}
_handle_onFixLastPaymentChange = (value) =>
{
this.setState({ fix_last_payment_available: value });
}
_handle_onDateOffsetTypeChange = (value) =>
{
this.setState({ date_offset_type: value });
}
_handle_onPeriodChange = (value) =>
{
this.setState({ period_new: value });
}
_handle_onSumChange = (value, error) =>
{
const { errors } = this.state;
if(error) { errors['sum'] = true; } else { delete errors['sum']; }
this.setState({ sum: value, errors });
}
_handle_onInsurancePriceChange = (value, error) =>
{
const { errors } = this.state;
if(error) { errors['insurance_price_result'] = true; } else { delete errors['insurance_price_result']; }
this.setState({ insurance_price_result: value, errors });
}
_handle_onInsuranceDateFromChange = (date) =>
{
this.setState({ datefrom: date });
}
_checkAllowCalculate = () =>
{
const { errors } = this.state;
for(let i in errors)
{
if(errors[i])
{
return false;
}
}
return true;
}
render()
{
const { loading, sending, } = this.state;
const { variants, options } = this.props;
/*this._checkAllowCalculate() ? this._handle_onCalculate : {}*/
return (
<div className="block">
<p className="title" style={{ fontSize: "16px" }}>{ options !== undefined && options !== null && options.number_planpayment_header.value }</p>
<p className="title">Параметры опций изменений графика платежей</p>
{ loading ? (
<div style={{ position: "absolute", left: "50%", top: "50%" }}>
<SpinnerCircular size={ 90 } thickness={ 51 } speed={ 100 } color="rgba(28, 1, 169, 1)" secondaryColor="rgba(236, 239, 244, 1)" style={{ marginTop: "-45px", marginLeft: "-45px", }}/>
</div>
) : (
<form className="calc" onSubmit={ this._handle_onCalculate }>
{ options !== undefined && options !== null && options.number_paydate !== undefined && options.number_paydate !== null && options.number_paydate.visible && (
<PaymentDate option={ options.number_paydate } onOption={ this._handle_onPaymentDateChange } />
) }
{ options !== undefined && options !== null && options.fix_last_payment_available !== undefined && options.fix_last_payment_available !== null && options.fix_last_payment_available.visible && (
<FixLastPayment option={ options.fix_last_payment_available } onOption={ this._handle_onFixLastPaymentChange } />
) }
{ options !== undefined && options !== null && options.date_offset_type !== undefined && options.date_offset_type !== null && options.date_offset_type.visible && (
<DateOffestType option={ options.date_offset_type } onOption={ this._handle_onDateOffsetTypeChange } />
) }
{ options !== undefined && options !== null && options.period_new !== undefined && options.period_new !== null && options.period_new.visible && (
<PeriodSelector option={ options.period_new } onOption={ this._handle_onPeriodChange } />
) }
{ options !== undefined && options !== null && options.sum !== undefined && options.sum !== null && options.sum.visible && (
<SumSelector option={ options.sum } onOption={ this._handle_onSumChange } onSubmit={ this._handle_onCalculate }/>
) }
{ options !== undefined && options !== null && options.insurance_price_result !== undefined && options.insurance_price_result !== null && options.insurance_price_result.visible && (
<InsurancePriceSelector option={ options.insurance_price_result } onOption={ this._handle_onInsurancePriceChange } onSubmit={ this._handle_onCalculate }/>
) }
{ options !== undefined && options !== null && options.datefrom !== undefined && options.datefrom !== null && options.datefrom.visible && (
<InsuranceDateFromSelector option={ options.datefrom } onOption={ this._handle_onInsuranceDateFromChange } />
) }
<div className="btn_group">
<button className="button button-gray" onClick={ this._handle_onBack }>Назад</button>
<button type="submit" className="button button-blue" disabled={ this._checkAllowCalculate() ? false : true } style={{ minWidth: 350 }}>
{ sending ? (
<SpinnerCircular size={24} thickness={100} speed={100} color="rgba(255, 255, 255, 1)" secondaryColor="rgba(255, 255, 255, 0.5)" style={{ marginTop: "0px" }}/>
) : ( "Рассчитать график" ) }
</button>
</div>
</form>
) }
</div>
);
}
}