616 lines
15 KiB
JavaScript
616 lines
15 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 DownloadFinesPdfButton from "../components/DownloadFinesPdfButton";
|
||
|
||
import {
|
||
getContractInfo,
|
||
getContractDocuments,
|
||
getReconciliationFile,
|
||
} from "../../actions";
|
||
|
||
const TYPES = {
|
||
upd: "УПД по очередным платежам",
|
||
upd_avans: "УПД по авансовым платежам",
|
||
billfines: "Счета-уведомления на пени",
|
||
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())
|
||
{
|
||
if (date >= valid_date_start && date <= valid_date_end)
|
||
{
|
||
if (date < period_date_end)
|
||
{
|
||
this.setState({
|
||
period_date_start: date,
|
||
reconciliation_disabled: false,
|
||
});
|
||
}
|
||
else
|
||
{
|
||
this.setState({
|
||
period_date_start: date,
|
||
reconciliation_disabled: true,
|
||
});
|
||
}
|
||
}
|
||
else
|
||
{
|
||
this.setState({
|
||
period_date_start: date,
|
||
reconciliation_disabled: true,
|
||
});
|
||
}
|
||
}
|
||
else
|
||
{
|
||
this.setState({ reconciliation_disabled: true });
|
||
}
|
||
};
|
||
|
||
_handle_onPeriodDate_end = (date) =>
|
||
{
|
||
console.log("_handle_onPeriodDate_end", "date", 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({
|
||
period_date_end: date,
|
||
reconciliation_disabled: true,
|
||
});
|
||
}
|
||
}
|
||
else
|
||
{
|
||
this.setState({ period_date_end: date, 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 !== 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="dosc_list medium-icon">
|
||
{ documents
|
||
.slice(0, opened.indexOf(type) > -1 ? documents.length : 3)
|
||
.map((doc, index) =>
|
||
{
|
||
console.log("doc", doc);
|
||
|
||
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}
|
||
/>
|
||
</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;
|
||
};
|
||
|
||
_renderFines = (fines, type) =>
|
||
{
|
||
console.log("_renderFines");
|
||
console.log("fines");
|
||
console.log(fines);
|
||
|
||
const { number } = this.props;
|
||
const { opened } = this.state;
|
||
|
||
const status = {
|
||
NotPaid: "danger",
|
||
PaidEvolution: "success",
|
||
PaidIndependently: "success",
|
||
};
|
||
|
||
if (fines.length > 0)
|
||
{
|
||
return (
|
||
<>
|
||
<div className="block-column">
|
||
<div
|
||
className={`dropdown_block ${
|
||
opened.indexOf("fines") > -1 ? "open" : ""
|
||
}`}
|
||
>
|
||
<div className="block_header">
|
||
<p>{ TYPES["fines"] }</p>
|
||
</div>
|
||
</div>
|
||
<div className="dropdown_blocks_list">
|
||
{ fines.slice(0, opened.indexOf("fines") > -1 ? fines.length : 3).map((fine, fine_index) => (
|
||
<div className="dropdown_block open" key={fine_index}>
|
||
<div className="block_body">
|
||
<div className="fines_detail">
|
||
<p>
|
||
№ постановления: <b>{fine.fine_number}</b>
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
Дата нарушения:{" "}
|
||
<b>
|
||
{moment(fine.violation_date).format("DD.MM.YYYY")}
|
||
</b>
|
||
</li>
|
||
{ fine.violation_place !== undefined && fine.violation_place !== null && (
|
||
<li>
|
||
Место нарушения: <b>{fine.violation_place}</b>
|
||
</li>
|
||
) }
|
||
<li>
|
||
Сумма:{" "}
|
||
<b style={{ whiteSpace: "nowrap" }}>
|
||
{numeral(fine.amount).format(" ., ")} ₽
|
||
</b>
|
||
</li>
|
||
{fine.gibdd !== undefined && fine.gibdd !== null && (
|
||
<li>
|
||
Подразделение: <b>{fine.gibdd}</b>
|
||
</li>
|
||
)}
|
||
<li>
|
||
Статус:{" "}
|
||
<b className={status[fine.status_code]}>
|
||
{fine.status}
|
||
</b>
|
||
</li>
|
||
</ul>
|
||
<p style={{ paddingTop: "15px" }}>
|
||
Штраф: {fine.fine_title}
|
||
</p>
|
||
</div>
|
||
{ fine.status_code !== "PaidIndependently" && (
|
||
<div className="dosc_list medium-icon">
|
||
<div className="row">
|
||
<p
|
||
className="doc_name i-pdf i-medium"
|
||
style={{ marginBottom: "0px" }}
|
||
>
|
||
Счет на оплату
|
||
</p>
|
||
<DownloadFinesPdfButton
|
||
className="download-icon"
|
||
filename={`evolution_fine_${fine.fine_number}.pdf`}
|
||
before={
|
||
fine.status_code === "NotPaid" ? true : false
|
||
}
|
||
contract={number}
|
||
num={fine.fine_number}
|
||
/>
|
||
</div>
|
||
</div>
|
||
) }
|
||
</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>
|
||
)) }
|
||
{ opened.indexOf(type) < 0 && fines.length > 3 && (
|
||
<div
|
||
className="row"
|
||
style={{
|
||
display: "flex",
|
||
justifyContent: "center",
|
||
corsor: "pointer",
|
||
}}
|
||
onClick={() => this._handle_onGroup(type)}
|
||
>
|
||
<p style={{ paddingTop: "15px", color: "#747474" }}>
|
||
Еще {fines.length - 3}{" "}
|
||
{pluralize(
|
||
fines.length - 3,
|
||
"постановлений",
|
||
"постановление",
|
||
"постановления",
|
||
"постановлений"
|
||
)}
|
||
</p>
|
||
</div>
|
||
) }
|
||
</div>
|
||
</div>
|
||
</>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<>
|
||
<div className="block-column">
|
||
<div
|
||
className={`dropdown_block ${
|
||
opened.indexOf(type) > -1 ? "open" : ""
|
||
}`}
|
||
>
|
||
<div
|
||
className="block_header"
|
||
onClick={ () => this._handle_onGroup(type) }
|
||
>
|
||
<p>{ TYPES[type] }</p>
|
||
</div>
|
||
</div>
|
||
<div style={{ display: "flex", alignItems: "center" }}>
|
||
<p>Штрафов не найдено.</p>
|
||
<p> </p>
|
||
</div>
|
||
</div>
|
||
</>
|
||
);
|
||
};
|
||
|
||
render()
|
||
{
|
||
const { number } = this.props;
|
||
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;
|
||
|
||
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 !== null
|
||
? car.vin_number
|
||
: "без VIN номера"
|
||
}`
|
||
: "" }
|
||
</h5>
|
||
</div>
|
||
<Company { ...this.props }/>
|
||
</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="dropdown_blocks_list">
|
||
{documents !== undefined && documents !== null ? (
|
||
<>
|
||
{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>
|
||
{*/
|
||
}
|