410 lines
11 KiB
JavaScript
410 lines
11 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 'moment/locale/ru';
|
||
|
||
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 DownloadPrintFormPdfButton from "../components/DownloadPrintFormPdfButton";
|
||
|
||
import PenaltiesCalculatorForm from "./components/PenaltiesCalculatorForm";
|
||
|
||
import {
|
||
getContractInfo,
|
||
getContractDocuments,
|
||
getReconciliationFile,
|
||
getContractPenalties,
|
||
} from "../../actions";
|
||
import AccountLayout from "../components/Layout/Account";
|
||
import ContractHeader from "./components/ContractHeader";
|
||
import ReconciliationForm from "./components/ReconciliationForm";
|
||
|
||
const TYPES = {
|
||
upd: "УПД по очередным платежам",
|
||
upd_avans: "УПД по авансовым платежам",
|
||
billfines: "Счета-уведомления на пени",
|
||
billgibdd: "BillGIBDD",
|
||
fines: "Штрафы ГИБДД",
|
||
};
|
||
|
||
class ContractDocumentsPage extends React.Component
|
||
{
|
||
constructor(props)
|
||
{
|
||
super(props);
|
||
this.state = {
|
||
loading: false,
|
||
contracts_info: {},
|
||
opened: [],
|
||
date: null,
|
||
car: null,
|
||
contract_date: null,
|
||
documents: null,
|
||
valid_date_start: null,
|
||
valid_date_end: null,
|
||
period_date_start: null,
|
||
period_date_end: null,
|
||
reconciliation_requested: false,
|
||
reconciliation_disabled: false,
|
||
penalties: false,
|
||
penalties_date: moment().format("YYYY.MM.DD"),
|
||
penalties_result: undefined,
|
||
};
|
||
|
||
this.penalties_form_ref = React.createRef();
|
||
}
|
||
|
||
static getDerivedStateFromProps(nextProps, prevState)
|
||
{
|
||
return {
|
||
contracts_info: nextProps.contracts_info,
|
||
documents: nextProps.documents,
|
||
};
|
||
}
|
||
|
||
componentDidMount()
|
||
{
|
||
const { dispatch, number} = this.props;
|
||
|
||
if(!this.state.loading && number !== undefined)
|
||
{
|
||
if(this.state.contracts_info[ number ] === undefined)
|
||
{
|
||
getContractInfo({ dispatch, number });
|
||
}
|
||
|
||
this.setState({ loading: true }, () =>
|
||
{
|
||
getContractDocuments({ dispatch, number, })
|
||
.then(() =>
|
||
{
|
||
this.setState({ loading: false });
|
||
})
|
||
.catch(() => {});
|
||
});
|
||
}
|
||
}
|
||
|
||
componentDidUpdate(prevProps, prevState)
|
||
{
|
||
if (prevState.loading && this.state.loading)
|
||
{
|
||
if(document.location.hash.indexOf("penalties") > -1)
|
||
{
|
||
setTimeout(() =>
|
||
{
|
||
if(this.penalties_form_ref.current !== undefined && this.penalties_form_ref.current !== null)
|
||
{
|
||
//console.log("this.penalties_form_ref.current", this.penalties_form_ref.current);
|
||
|
||
this.penalties_form_ref.current.scrollIntoView({
|
||
behavior: 'smooth',
|
||
block: 'center',
|
||
});
|
||
}
|
||
}, 100);
|
||
}
|
||
}
|
||
}
|
||
|
||
_handle_onGroup = (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 !== undefined && documents !== null)
|
||
{
|
||
if (documents.length > 0)
|
||
{
|
||
return (
|
||
<>
|
||
<div className="block-column">
|
||
<div
|
||
className={`dropdown_block ${ opened.indexOf(type) > -1 ? "open" : "" }`}
|
||
>
|
||
<div className="block_header default">
|
||
<p>{TYPES[type]}</p>
|
||
</div>
|
||
</div>
|
||
<div className="docs_list medium-icon">
|
||
{ documents
|
||
.slice(0, opened.indexOf(type) > -1 ? documents.length : 3)
|
||
.map((doc, index) =>
|
||
{
|
||
return (
|
||
<div className="row" key={index}>
|
||
<p
|
||
className="doc_name i-pdf i-medium"
|
||
data-format={doc.extension}
|
||
>
|
||
{doc.num} от {moment(doc.date).format("DD.MM.YYYY")}
|
||
</p>
|
||
<DownloadPrintFormPdfButton
|
||
className="download-icon"
|
||
filename={ `${ number }_${ doc.type }_${ doc.num }.${ doc.extension }` }
|
||
contract={ number }
|
||
num={ doc.num }
|
||
date={ doc.date }
|
||
type={ doc.type }
|
||
log={{
|
||
contract_number: number,
|
||
document_type: doc.type,
|
||
document_name: doc.num,
|
||
document_date: doc.date,
|
||
}}
|
||
/>
|
||
</div>
|
||
);
|
||
}) }
|
||
{ opened.indexOf(type) < 0 && documents.length > 3 && (
|
||
<div
|
||
className="row click-more"
|
||
onClick={ () => this._handle_onGroup(type) }
|
||
>
|
||
<p>
|
||
Еще {documents.length - 3}{" "}
|
||
{ pluralize(
|
||
documents.length - 3,
|
||
"документов",
|
||
"документ",
|
||
"документа",
|
||
"документов"
|
||
) }
|
||
</p>
|
||
</div>
|
||
) }
|
||
</div>
|
||
</div>
|
||
</>
|
||
);
|
||
}
|
||
|
||
if (type !== "upd_avans" && type !== "billfines")
|
||
{
|
||
return (
|
||
<>
|
||
<div className="block-column">
|
||
<div
|
||
className={`dropdown_block ${ opened.indexOf(type) > -1 ? "open" : "" }`}
|
||
>
|
||
<div className="block_header">
|
||
<p>{ TYPES[ type ] }</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<p>Документов пока еще нет.</p>
|
||
<p> </p>
|
||
</div>
|
||
</div>
|
||
</>
|
||
);
|
||
}
|
||
}
|
||
|
||
return null;
|
||
};
|
||
|
||
_handle_onPenaltiesShow = (date) =>
|
||
{
|
||
const { number } = this.props;
|
||
|
||
window.scrollTo(0, 0);
|
||
this.setState({ penalties: true, penalties_date: date, penalties_result: undefined }, () =>
|
||
{
|
||
getContractPenalties({ number, date })
|
||
.then((result) =>
|
||
{
|
||
this.setState({ penalties_result: result });
|
||
})
|
||
.catch(() =>
|
||
{
|
||
|
||
});
|
||
});
|
||
}
|
||
|
||
_handle_onPenaltiesHide = () =>
|
||
{
|
||
this.setState({ penalties: false, penalties_result: undefined }, () =>
|
||
{
|
||
});
|
||
}
|
||
|
||
render()
|
||
{
|
||
const { number } = this.props;
|
||
const { loading, contracts_info, documents, penalties, penalties_date, penalties_result, } = this.state;
|
||
|
||
let { date, car, status } = contracts_info[ number ] !== undefined ? contracts_info[ number ] : {};
|
||
|
||
return (
|
||
<React.Fragment>
|
||
<Head>
|
||
<title>ЛК Эволюция автолизинга</title>
|
||
<meta name="description" content="ЛК Эволюция автолизинга" />
|
||
</Head>
|
||
<Header { ...this.props }/>
|
||
<AccountLayout>
|
||
{ penalties ? (
|
||
<>
|
||
<div className="title_wrapper">
|
||
<div className="left" style={{ alignItems: "center", flexWrap: "wrap", alignItems: "flex-start" }}>
|
||
<button className="back" onClick={ this._handle_onPenaltiesHide }>Назад</button>
|
||
<div style={{ flexDirection: "column" }}>
|
||
<h1 className="section_title">Расчет планируемых пени</h1>
|
||
<h5 style={{ fontSize: "14px" }}>
|
||
Договор №{ number }
|
||
{ 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 !== null ? car.vin_number : "без VIN номера" }` : "" }
|
||
</h5>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div className="aside_container about">
|
||
<article className="fine">
|
||
<div className="fine_block">
|
||
<div className="fine_col">
|
||
<p>
|
||
<span>Пени на дату</span>
|
||
{ moment(penalties_date, "YYYY.MM.DD").format("DD.MM.YYYY") }
|
||
</p>
|
||
</div>
|
||
{ penalties_result === undefined ? (
|
||
<div
|
||
style={{ minHeight: 200, 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>
|
||
) : (
|
||
<>
|
||
{ penalties_result.length > 0 ? (
|
||
<div className="fine_col">
|
||
{ penalties_result.map((bill, index) => (
|
||
<p key={ index }>
|
||
{ moment(bill.dateBillout, "YYYY-MM-DD").format("MMMM") }
|
||
<span>{ numeral(bill.sumBill).format(' ., ') } ₽</span>
|
||
</p>
|
||
)) }
|
||
</div>
|
||
) : (
|
||
<p>К сожалению на указанную дату расчет пени невозможен.</p>
|
||
) }
|
||
</>
|
||
)}
|
||
</div>
|
||
</article>
|
||
</div>
|
||
</>
|
||
) : (
|
||
<>
|
||
<div className="title_wrapper">
|
||
<div className="left" style={{ flexDirection: "column" }}>
|
||
<ContractHeader number={ number } date={ date } car={ car }/>
|
||
</div>
|
||
<Company { ...this.props }/>
|
||
</div>
|
||
<div className="aside_container about">
|
||
<InnerMenu number={ number } status={ status } { ...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>
|
||
) : (
|
||
<>
|
||
<ReconciliationForm number={ number } contract_date={ date }/>
|
||
<div className="dropdown_blocks_list">
|
||
{documents !== undefined && documents !== null ? (
|
||
<>
|
||
{this._renderDocuments(documents.upd, "upd")}
|
||
{this._renderDocuments(
|
||
documents.upd_avans,
|
||
"upd_avans"
|
||
)}
|
||
{this._renderDocuments(
|
||
documents.billfines,
|
||
"billfines"
|
||
)}
|
||
</>
|
||
) : null}
|
||
{ documents !== undefined && documents !== null && documents.billfines !== undefined && documents.billfines !== null && documents.billfines.length > 0 && (
|
||
<div className="block-column" ref={ this.penalties_form_ref }>
|
||
<PenaltiesCalculatorForm onPenalties={ this._handle_onPenaltiesShow }/>
|
||
</div>
|
||
) }
|
||
</div>
|
||
</>
|
||
) }
|
||
</article>
|
||
</div>
|
||
</>
|
||
) }
|
||
</AccountLayout>
|
||
<Footer/>
|
||
</React.Fragment>
|
||
);
|
||
}
|
||
}
|
||
|
||
function mapStateToProps(state, ownProps)
|
||
{
|
||
return {
|
||
contracts_info: state.contracts_info,
|
||
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)); |