428 lines
13 KiB
JavaScript
428 lines
13 KiB
JavaScript
import React from "react";
|
||
import Head from 'next/head';
|
||
import Image from 'next/image';
|
||
import { connect } from "react-redux";
|
||
import { withRouter } from 'next/router';
|
||
import moment from "moment";
|
||
import numeral from "numeral";
|
||
import { SpinnerCircular } from 'spinners-react';
|
||
import pluralize from 'pluralize-ru';
|
||
|
||
import { reduxWrapper } from '../../store';
|
||
|
||
import Header from '../components/Header';
|
||
import Footer from '../components/Footer';
|
||
import InnerMenu from "./components/InnerMenu";
|
||
import Company from "../components/Company";
|
||
import DateInput from '../components/DatePicker';
|
||
import DownloadPrintFormPdfButton from "../components/DownloadPrintFormPdfButton";
|
||
|
||
import { getContractInfo, getContractDocuments, getReconciliationFile } from "../../actions";
|
||
|
||
const TYPES = {
|
||
upd: "УПД по очередным платежам",
|
||
upd_avans: "УПД по авансовым платежам",
|
||
billgibdd: "BillGIBDD",
|
||
fines: "Штрафы ГИБДД",
|
||
};
|
||
|
||
class ContractDocumentsPage extends React.Component
|
||
{
|
||
constructor(props)
|
||
{
|
||
super(props);
|
||
this.state = {
|
||
opened: [],
|
||
date: null,
|
||
car: null,
|
||
contract_date: null,
|
||
documents: null,
|
||
loading: false,
|
||
valid_date_start: null,
|
||
valid_date_end: null,
|
||
period_date_start: null,
|
||
period_date_end: null,
|
||
reconciliation_requested: false,
|
||
reconciliation_disabled: false,
|
||
}
|
||
}
|
||
|
||
static getDerivedStateFromProps(nextProps, prevState)
|
||
{
|
||
return {
|
||
date: nextProps.date,
|
||
car: nextProps.car,
|
||
contract_date: nextProps.contract_date,
|
||
documents: nextProps.documents,
|
||
};
|
||
}
|
||
|
||
componentDidMount()
|
||
{
|
||
if(!this.state.loading && this.props.number !== undefined)
|
||
{
|
||
const de = moment().toDate();
|
||
this.setState({ loading: true, period_date_end: de, valid_date_end: de }, () =>
|
||
{
|
||
getContractInfo({ dispatch: this.props.dispatch, number: this.props.number });
|
||
|
||
getContractDocuments({ dispatch: this.props.dispatch, number: this.props.number }).then(() => {
|
||
this.setState({ loading: false });
|
||
}).catch(() => {});
|
||
});
|
||
}
|
||
}
|
||
|
||
componentDidUpdate(prevProps, prevState)
|
||
{
|
||
if(this.state.period_date_start === null)
|
||
{
|
||
if(prevState.contract_date === null && this.state.contract_date !== null)
|
||
{
|
||
const ds = moment(this.state.contract_date).toDate();
|
||
this.setState({ period_date_start: ds, valid_date_start: ds });
|
||
}
|
||
}
|
||
}
|
||
|
||
_handle_onReconciliationFileRequest = () =>
|
||
{
|
||
const { number } = this.props;
|
||
const { reconciliation_requested, period_date_start, period_date_end, } = this.state;
|
||
|
||
if(!reconciliation_requested)
|
||
{
|
||
this.setState({ reconciliation_requested: true }, () =>
|
||
{
|
||
const date_from = moment(period_date_start).format("YYYY-MM-DD");
|
||
const date_to = moment(period_date_end).format("YYYY-MM-DD");
|
||
|
||
getReconciliationFile({
|
||
contract: number,
|
||
date_from: date_from,
|
||
date_to: date_to,
|
||
filename: `${ number }_reconciliation_${ date_from }_${ date_to }.pdf`,
|
||
})
|
||
.then(() =>
|
||
{
|
||
this.setState({ reconciliation_requested: false });
|
||
})
|
||
.catch(() =>
|
||
{
|
||
this.setState({ reconciliation_requested: false });
|
||
});
|
||
});
|
||
}
|
||
}
|
||
|
||
_handle_onPeriodDate_start = (date) =>
|
||
{
|
||
const { valid_date_start, valid_date_end, period_date_start, period_date_end } = this.state;
|
||
const md = moment(date, "DD.MM.YYYY");
|
||
|
||
if(md.isValid())
|
||
{
|
||
console.log(md);
|
||
console.log("vs", valid_date_start);
|
||
console.log("ve", valid_date_end);
|
||
|
||
if(date >= valid_date_start && date < valid_date_end)
|
||
{
|
||
console.log("ps", period_date_start);
|
||
if(date < period_date_end)
|
||
{
|
||
console.log(">>>>>");
|
||
this.setState({ period_date_start: date, reconciliation_disabled: false });
|
||
}
|
||
else
|
||
{
|
||
this.setState({ reconciliation_disabled: true });
|
||
}
|
||
}
|
||
else
|
||
{
|
||
this.setState({ reconciliation_disabled: true });
|
||
}
|
||
}
|
||
else
|
||
{
|
||
console.log("invalid date", md);
|
||
this.setState({ reconciliation_disabled: true });
|
||
}
|
||
}
|
||
|
||
_handle_onPeriodDate_end = (date) =>
|
||
{
|
||
const { valid_date_start, valid_date_end, period_date_start, period_date_end } = this.state;
|
||
|
||
if(moment(date).isValid())
|
||
{
|
||
if(date >= valid_date_start && date < valid_date_end)
|
||
{
|
||
if(date > period_date_start)
|
||
{
|
||
this.setState({ period_date_end: date, reconciliation_disabled: false });
|
||
}
|
||
else
|
||
{
|
||
this.setState({ reconciliation_disabled: true });
|
||
}
|
||
}
|
||
else
|
||
{
|
||
this.setState({ reconciliation_disabled: true });
|
||
}
|
||
}
|
||
else
|
||
{
|
||
this.setState({ reconciliation_disabled: true });
|
||
}
|
||
}
|
||
|
||
_handle_onGroup = (group) =>
|
||
{
|
||
console.log("group", group);
|
||
const opened = [ ...this.state.opened ];
|
||
|
||
if(opened.indexOf(group) < 0)
|
||
{ opened.push(group); }
|
||
else
|
||
{ opened.splice(opened.indexOf(group), 1); }
|
||
|
||
this.setState({ opened: opened });
|
||
}
|
||
|
||
_renderDocuments = (documents, type) =>
|
||
{
|
||
const { number } = this.props;
|
||
const { opened } = this.state;
|
||
|
||
if(documents.length > 0)
|
||
{
|
||
return (
|
||
<>
|
||
<div className={`dropdown_block bt ${ opened.indexOf(type) > -1 ? "open" : "" }`}>
|
||
<div className="block_header" onClick={ () => this._handle_onGroup(type) }>
|
||
<p>{ TYPES[type] }</p>
|
||
{ documents.length > 3 && (
|
||
<button className={`block_toggle ${ opened.indexOf(type) > -1 ? "rotate" : "" }`}></button>
|
||
) }
|
||
</div>
|
||
</div>
|
||
<div className="dosc_list medium-icon">
|
||
{ documents.slice(0, opened.indexOf(type) > -1 ? documents.length : 3).map((doc, index) => (
|
||
<div className="row" key={ index }>
|
||
<p className="doc_name i-pdf i-medium">
|
||
{ doc.num } от { moment(doc.date).format("DD.MM.YYYY") }
|
||
</p>
|
||
<DownloadPrintFormPdfButton className="download-icon" filename={ `${ number }_${ doc.type }_${ doc.num }.pdf` } contract={ number } num={ doc.num } date={ doc.date } type={ doc.type }/>
|
||
</div>
|
||
)) }
|
||
{ opened.indexOf(type) < 0 && documents.length > 3 && (
|
||
<div className="row" style={{ justifyContent: "center", corsor: "pointer" }} onClick={ () => this._handle_onGroup(type) }>
|
||
<p style={{ color: "#747474" }}>Еще { documents.length - 3 } { pluralize((documents.length - 3), 'документов', 'документ', 'документа', 'документов') }</p>
|
||
</div>
|
||
) }
|
||
</div>
|
||
</>
|
||
)
|
||
}
|
||
|
||
if(type !== "upd_avans")
|
||
{
|
||
return (
|
||
<>
|
||
<div className={`dropdown_block bt ${ opened.indexOf(type) > -1 ? "open" : "" }`}>
|
||
<div className="block_header" onClick={ () => this._handle_onGroup(type) }>
|
||
<p>{ TYPES[type] }</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<p>Документов пока еще нет.</p>
|
||
<p> </p>
|
||
</div>
|
||
</>
|
||
);
|
||
}
|
||
}
|
||
|
||
_renderFines = (fines, type) =>
|
||
{
|
||
const { number } = this.props;
|
||
const { opened } = this.state;
|
||
|
||
if(fines.length > 0)
|
||
{
|
||
<>
|
||
<div className={`dropdown_block bt ${ opened.indexOf('fines') > -1 ? "open" : "" }`}>
|
||
<div className="block_header" onClick={ () => this._handle_onGroup('fines') }>
|
||
<p>{ TYPES[ 'fines' ] }</p>
|
||
{ fines.length > 3 && (
|
||
<button className={`block_toggle ${ opened.indexOf('fines') > -1 ? "rotate" : "" }`}></button>
|
||
) }
|
||
</div>
|
||
</div>
|
||
<div className="dosc_list medium-icon">
|
||
{ fines.slice(0, opened.indexOf('fines') > -1 ? fines.length : 3).map((fine, fine_index) => (
|
||
<div className="row" key={ fine_index }>
|
||
<div className="block_body" >
|
||
<div className="transaction_detail">
|
||
<p>№ постановления: <b>{ fine.fine_number }</b></p>
|
||
<ul>
|
||
<li>Сумма: <b>{ numeral(fine.amount).format(' ., ') } ₽</b></li>
|
||
<li>Дата: <b>{ moment(fine.fine_date).format("DD.MM.YYYY") }</b></li>
|
||
<li>Статус: <b className="success">{ fine.status }</b></li>
|
||
<li>Штраф: { fine.fine_title }</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
{ opened.indexOf(type) < 0 && fines.length > 3 && (
|
||
<div className="row" style={{ justifyContent: "center", corsor: "pointer" }} onClick={ () => this._handle_onGroup(type) }>
|
||
<p style={{ color: "#747474" }}>Еще { fines.length - 3 } { pluralize((fines.length - 3), 'постановлений', 'постановление', 'постановления', 'постановлений') }</p>
|
||
</div>
|
||
) }
|
||
|
||
{/*}
|
||
<DownloadPrintFormPdfButton className="download-icon" filename={ `${ number }_${ upd_document.type }_${ upd_document.num }.pdf` } contract={ number } num={ upd_document.num } date={ upd_document.date } type={ upd_document.type }/>
|
||
{*/}
|
||
</div>
|
||
)) }
|
||
</div>
|
||
</>
|
||
}
|
||
|
||
return (
|
||
<>
|
||
<div className={`dropdown_block bt ${ opened.indexOf(type) > -1 ? "open" : "" }`}>
|
||
<div className="block_header" onClick={ () => this._handle_onGroup(type) }>
|
||
<p>{ TYPES[type] }</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<p>Штрафов не найдено.</p>
|
||
<p> </p>
|
||
</div>
|
||
</>
|
||
);
|
||
}
|
||
|
||
render()
|
||
{
|
||
const { loading, date, car, contract_date, documents, period_date_start, period_date_end, valid_date_start, valid_date_end, reconciliation_requested, reconciliation_disabled, opened } = this.state;
|
||
const { number } = this.props;
|
||
|
||
console.log("documentsdocumentsdocumentsdocumentsdocuments");
|
||
console.log(documents);
|
||
|
||
console.log("opened");
|
||
console.log(opened);
|
||
|
||
return (
|
||
<React.Fragment>
|
||
<Head>
|
||
<title>ЛК Эволюция автолизинга</title>
|
||
<meta
|
||
name="description"
|
||
content="ЛК Эволюция автолизинга"
|
||
/>
|
||
</Head>
|
||
<Header {...this.props} />
|
||
<main>
|
||
<section>
|
||
<div className="clear"></div>
|
||
<div className="container">
|
||
<div className="title_wrapper">
|
||
<div className="left" style={{ flexDirection: 'column', }}>
|
||
<h1 className="section_title">Договор №{ number }</h1>
|
||
<h5 style={{ fontSize: '14px' }}>{ date !== undefined && date !== null && date !== null && (<> от { moment(date).format("DD.MM.YYYY") }</>)}{ car !== undefined && car !== null ? ` - ${ car.brand.name } ${ car.model.name } | ${ car.reg_number !== null ? car.reg_number : 'без рег. номера' } | ${ car.vin_number }` : '' }</h5>
|
||
</div>
|
||
<Company />
|
||
</div>
|
||
<div className="aside_container about">
|
||
<InnerMenu number={ number } {...this.props} />
|
||
<article>
|
||
{ loading ? (
|
||
<div className="table_row table_header" style={{ minHeight: 300, display: "flex", justifyContent: "center", alignItems: "center" }}>
|
||
<SpinnerCircular size={90} thickness={51} speed={100} color="rgba(28, 1, 169, 1)" secondaryColor="rgba(236, 239, 244, 1)" />
|
||
</div>
|
||
) : (
|
||
<>
|
||
<div className="reconciliation_form">
|
||
<p>Акт сверки</p>
|
||
<div className="form_group">
|
||
<div className="form_field">
|
||
<DateInput placeholder="Дата начала периода" value={ period_date_start } min={ valid_date_start } max={ valid_date_end } onChange={ this._handle_onPeriodDate_start }/>
|
||
</div>
|
||
<div className="form_field">
|
||
<DateInput placeholder="Дата окончания периода" value={ period_date_end } min={ valid_date_start } max={ valid_date_end } onChange={ this._handle_onPeriodDate_end }/>
|
||
</div>
|
||
</div>
|
||
<div className="form_group">
|
||
<button className="button button-blue" disabled={ reconciliation_disabled } onClick={ () => { this._handle_onReconciliationFileRequest() }}>
|
||
<>
|
||
{ reconciliation_requested ? (
|
||
<SpinnerCircular size={24} thickness={100} speed={100} color="rgba(255, 255, 255, 1)" secondaryColor="rgba(255, 255, 255, 0.5)" />
|
||
) : "Скачать" }
|
||
</>
|
||
</button>
|
||
{/*<button className="button button-blue">Отправить в ЭДО</button>*/}
|
||
</div>
|
||
</div>
|
||
<div className="dropdown_blocks_list">
|
||
{ documents !== undefined && documents !== null ? (
|
||
<>
|
||
{ this._renderDocuments(documents.upd, 'upd') }
|
||
{ this._renderDocuments(documents.upd_avans, 'upd_avans') }
|
||
{ this._renderFines(documents.fines, 'fines') }
|
||
</>
|
||
) : null }
|
||
</div>
|
||
</>
|
||
) }
|
||
</article>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
<Footer />
|
||
</React.Fragment>
|
||
);
|
||
}
|
||
}
|
||
|
||
function mapStateToProps(state, ownProps)
|
||
{
|
||
return {
|
||
contract_date: state.contract.date,
|
||
date: state.contract.date,
|
||
car: state.contract.car,
|
||
documents: state.contract.documents,
|
||
}
|
||
}
|
||
|
||
export const getServerSideProps = reduxWrapper.getServerSideProps(store =>
|
||
async ({ req, res, query }) =>
|
||
{
|
||
return {
|
||
props: {
|
||
number: query.number,
|
||
}
|
||
}
|
||
}
|
||
);
|
||
|
||
export default withRouter(connect(mapStateToProps)(ContractDocumentsPage));
|
||
|
||
{/*}
|
||
<div className="block_body">
|
||
<div className="transaction_detail">
|
||
<p>№ постановления: <b>3432434242334</b></p>
|
||
<ul>
|
||
<li>Сумма: <b>3 000,00 р.</b></li>
|
||
<li>Дата: <b>01/01/2020</b></li>
|
||
<li>Статус: <b className="success">Оплачен</b></li>
|
||
<li>Штраф: п. 1.15 - Несоблюдение правил парковки </li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
{*/} |