events, graphic changes, support

This commit is contained in:
merelendor 2022-08-08 07:05:49 +03:00
parent 6196d48b9a
commit 737516743b
67 changed files with 7118 additions and 3408 deletions

View File

@ -152,8 +152,9 @@ export const logout = ({ dispatch }) =>
{
const cookies = new Cookies();
cookies.remove('jwt');
cookies.remove('observer');
dispatch({ type: actionTypes.AUTH, data: { logged: false } });
dispatch({ type: actionTypes.AUTH, data: { logged: false, observer: false } });
dispatch({ type: actionTypes.USER, data: {} });
dispatch({ type: actionTypes.COMPANY, data: {} });
@ -161,3 +162,51 @@ export const logout = ({ dispatch }) =>
Router.push('/');
});
}
export const sendOffstageToken = ({ token, dispatch }) =>
{
console.log("ACTION", "sendOffstageToken()", `${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/auth/offstage/`);
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/auth/offstage/`, { token })
.then((response) =>
{
console.log("sendOffstageToken RESPONSE");
console.log(response.data);
if(response.data.status === "success")
{
const cookies = new Cookies();
cookies.set('jwt', response.data.token, new Date(moment().add(7, 'day').toDate()));
cookies.set('observer', true, new Date(moment().add(7, 'day').toDate()));
getCompanyInfo({ dispatch })
.then(() =>
{
dispatch({ type: actionTypes.AUTH, data: { logged: true, observer: true } });
dispatch({ type: actionTypes.USER, data: response.data.user });
resolve();
Router.push('/');
})
.catch(() =>
{
reject();
});
//dispatch({ type: actionTypes.COMPANY, data: response.data.company });
}
else
{
reject();
}
})
.catch((error) =>
{
console.log("error");
console.error(error);
reject();
});
});
}

View File

@ -318,4 +318,225 @@ export const getContractMaterials = ({ dispatch, }) =>
reject();
});
});
}
export const getContractPenalties = ({ number, date }) =>
{
console.log("ACTION", "getContractPenalties", { number, date });
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/penalties`, {
number, date
},
{
withCredentials: true,
})
.then(async (response) =>
{
console.log("getContractPenalties", "response.data", response.data);
resolve(response.data);
})
.catch((error) =>
{
console.error(error);
reject();
});
});
}
export const getContractGraphicChange = ({ dispatch, number }) =>
{
return new Promise(async (resolve, reject) =>
{
await Promise.all([
getContractGraphicChangeSignatories({ dispatch, number }),
getContractGraphicChangeVariants({ dispatch, number, variants: {
change_payment_date: false,
insurance_change: false,
last_payment_change: false,
date_offset_change: false,
contract_term_change: false,
sum_pay_change: false,
early_redemption_change: false,
} }),
getContractGraphicChangeCalculationsList({ dispatch, number }),
])
.then(() =>
{
resolve();
});
});
}
export const getContractGraphicChangeSignatories = ({ dispatch, number }) =>
{
console.log("ACTION", "getContractGraphicChangeSignatories", { number });
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/change/signatories`, { number },
{
withCredentials: true,
})
.then(async (response) =>
{
console.log("ACTION", "getContractGraphicChangeSignatories", "response.data", response.data);
dispatch({ type: actionTypes.CONTRACT_CHANGE, data: { signatories: response.data.signatories } });
resolve();
})
.catch((error) =>
{
console.error("ACTION", "getContractGraphicChangeSignatories", "error");
console.error(error);
reject();
});
});
}
export const getContractGraphicChangeVariants = ({ dispatch, number, variants = {} }) =>
{
console.log("ACTION", "getContractGraphicChangeVariants", { ...{ number }, ...variants });
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/change/variants`, { ...{ number }, ...variants },
{
withCredentials: true,
})
.then(async (response) =>
{
console.log("ACTION", "getContractGraphicChangeVariants", "response.data", response.data);
dispatch({ type: actionTypes.CONTRACT_CHANGE, data: { variants: response.data } });
resolve();
})
.catch((error) =>
{
console.error("ACTION", "getContractGraphicChangeVariants", "error");
console.error(error);
reject();
});
});
}
export const getContractGraphicChangeCalculationsList = ({ dispatch, number }) =>
{
console.log("ACTION", "getContractGraphicChangeCalculationsList", { number });
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/change/calculations`, { number },
{
withCredentials: true,
})
.then(async (response) =>
{
console.log("ACTION", "getContractGraphicChangeCalculationsList", "response.data", response.data);
dispatch({ type: actionTypes.CONTRACT_CHANGE, data: { calculations: response.data.pre_calculations } });
resolve();
})
.catch((error) =>
{
console.error("ACTION", "getContractGraphicChangeCalculationsList", "error");
console.error(error);
reject();
});
});
}
export const getContractGraphicChangeOptions = ({ dispatch, number }) =>
{
return new Promise((resolve, reject) =>
{
resolve();
});
}
export const getContractGraphicChangeCalculate = ({ dispatch, number, calculation }) =>
{
console.log("ACTION", "getContractGraphicChangeCurrent", { number });
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/change/calculations`, { number },
{
withCredentials: true,
})
.then(async (response) =>
{
console.log("ACTION", "getContractGraphicChangeCurrent", "response.data", response.data);
dispatch({ type: actionTypes.CONTRACT_CHANGE, data: { calculations: response.data.pre_calculations } });
resolve();
})
.catch((error) =>
{
console.error("ACTION", "getContractGraphicChangeCurrent", "error");
console.error(error);
reject();
});
});
}
export const getContractGraphicChangeGetCurrent = ({ dispatch, number }) =>
{
console.log("ACTION", "getContractGraphicChangeGetCurrent", { number });
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/change/graphic/current`, { number },
{
withCredentials: true,
})
.then(async (response) =>
{
console.log("ACTION", "getContractGraphicChangeGetCurrent", "response.data", response.data);
dispatch({ type: actionTypes.CONTRACT_CHANGE, data: { current: response.data.planpayments } });
resolve();
})
.catch((error) =>
{
console.error("ACTION", "getContractGraphicChangeGetCurrent", "error");
console.error(error);
reject();
});
});
}
export const getContractGraphicChangeGetCalculated = ({ dispatch, calculation }) =>
{
console.log("ACTION", "getContractGraphicChangeGetCalculated", { calculation });
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/change/graphic/calculation`, { calculation },
{
withCredentials: true,
})
.then(async (response) =>
{
console.log("ACTION", "getContractGraphicChangeGetCalculated", "response.data", response.data);
dispatch({ type: actionTypes.CONTRACT_CHANGE, data: { calculated: response.data.planpayments } });
resolve();
})
.catch((error) =>
{
console.error("ACTION", "getContractGraphicChangeGetCalculated", "error");
console.error(error);
reject();
});
});
}
export const signContractGraphicChange = ({ dispatch, number }) =>
{
return new Promise((resolve, reject) =>
{
resolve();
});
}

View File

@ -2,6 +2,7 @@ import axios from 'axios';
import { Cookies } from 'react-cookie';
import Router from 'next/router';
import moment from 'moment';
import { nSQL } from "@nano-sql/core";
import * as actionTypes from '../constants/actionTypes';
@ -21,9 +22,10 @@ if(process.browser)
};
}
export const getEvents = ({ dispatch }) =>
export const getEvents = ({ dispatch, type, contract }) =>
{
console.log("getEvents");
console.log("getEvents", `${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/events`);
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/events`, {}, {
@ -32,8 +34,13 @@ export const getEvents = ({ dispatch }) =>
.then((response) =>
{
console.log("getEvents", "response", response.data);
const events = response.data;
const filtered_events = [];
dispatch({ type: actionTypes.EVENTS, data: { list: response.data } });
console.log("events");
console.log(events);
dispatch({ type: actionTypes.EVENTS, data: { list: events, loaded: true } });
resolve();
})
.catch((error) =>
@ -45,3 +52,81 @@ export const getEvents = ({ dispatch }) =>
});
});
}
export const getFilteredEvents = ({ dispatch, type, search, contract }) =>
{
return new Promise((resolve, reject) =>
{
console.log("getFilteredEvents");
const types = {
"restrictions": "restrictions",
"payments": [ "kasko_prolong", "fingap_prolong", "osago_prolong" ],
"additional": "graph_change",
"finance": "end_contract",
"fines": "fine_gibdd",
"pts": "return_pts",
};
if(type !== undefined || (search !== undefined || search !== null || search !== ""))
{
console.log(global.store.getState().events);
const events = global.store.getState().events.list;
let query = nSQL(events)
.query("select");
if(type !== undefined)
{
if(typeof types[ type ] === "string")
{
query.where([ [ "event_type", "=", types[ type ] ] ])
}
else
{
let array_of_queries = [];
for(let i in types[ type ])
{
array_of_queries.push([ "event_type", "=", types[ type ][ i ] ]);
if(parseInt(i, 10) < parseInt(types[ type ].length - 1))
{
console.log(parseInt(i, 10), "<", types[ type ].length - 1);
array_of_queries.push("OR");
}
}
console.log("array_of_queries", array_of_queries);
query.where(array_of_queries);
}
}
if(contract !== undefined && contract !== null && contract !== "")
{
query.where([ [ "contract_number", "=", contract ] ]);
}
if(search !== undefined && search !== null && search !== "")
{
query.where([ [ "contract_number", "LIKE", `%${ search }%` ], "OR", [ "add_info", "LIKE", `%${ search }%` ]]);
}
query.exec().then((rows) =>
{
console.log("rows");
console.log(rows);
dispatch({ type: actionTypes.EVENTS_FILTERED, data: { filtered: rows } });
resolve();
//callback(null, rows);
});
/*
.orderBy("number", "asc")
*/
}
else
{
dispatch({ type: actionTypes.EVENTS_FILTERED, data: { filtered: undefined } });
resolve();
}
});
}

View File

@ -22,18 +22,29 @@ if(process.browser)
};
}
export const getImage = async ({ id }) =>
export const getImage = ({ id }) =>
{
console.log("getImage");
const response = await axios.get(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/file/image`, {
params: { id },
responseType: 'blob',
console.log("getImage\n\n");
console.log("getImage", `${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/file/image`);
return new Promise((resolve, reject) =>
{
axios.get(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/file/image`, {
params: { id },
//responseType: 'blob',
})
.then((response) =>
{
resolve(response.data);
})
.catch((error) =>
{
console.error("getImage error");
console.error(error);
reject();
});
});
console.log("getImage", "response");
console.log(response);
return response;
}
export const getFile = ({ id, filename }) =>

View File

@ -13,5 +13,14 @@ export const CONTRACT_AGREEMENT = 'CONTRACT_AGREEMENT';
export const CONTRACT_DOCUMENTS = 'CONTRACT_DOCUMENTS';
export const CONTRACT_RULES = 'CONTRACT_RULES';
export const CONTRACT_MATERIALS = 'CONTRACT_MATERIALS';
export const CONTRACT_CHANGE = 'CONTRACT_CHANGE';
export const CONTRACT_SIGNATORIES = 'CONTRACT_SIGNATORIES';
export const CONTRACT_VARIANTS = 'CONTRACT_VARIANTS';
export const CONTRACT_OPTIONS = 'CONTRACT_OPTIONS';
export const CONTRACT_CURRENT = 'CONTRACT_CURRENT';
export const CONTRACT_CALCULATED = 'CONTRACT_CALCULATED';
export const CALENDAR = 'CALENDAR';
export const EVENTS = 'EVENTS';
export const EVENTS = 'EVENTS';
export const EVENTS_FILTERED = 'EVENTS_FILTERED';

File diff suppressed because one or more lines are too long

View File

@ -198,7 +198,7 @@ input[type="checkbox"] {
}
&:disabled + label {
&:before {
background: url("/assets/images/icons/checkbox_gray.svg") no-repeat center var(--gray-light);
//background: url("/assets/images/icons/checkbox_gray.svg") no-repeat center var(--gray-light);
cursor: none;
border-color: var(--gray-light);
}

File diff suppressed because one or more lines are too long

View File

@ -552,3 +552,14 @@ div {
line-height: 20px;
}
}
.interactive {
cursor: pointer;
}
.unselectable {
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}

68
lib/CRMRequest/index.js Normal file
View File

@ -0,0 +1,68 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import axios from 'axios';
import { Cookies } from 'react-cookie';
import cookie from 'cookie';
import moment from 'moment';
import jwt from 'jsonwebtoken';
import { cors } from '../cors';
export default async function CRMRequest(req, res, path, params)
{
await cors(req, res);
if(req.headers.cookie !== undefined)
{
const cookies = cookie.parse(req.headers?.cookie ? req.headers?.cookie : "");
console.log("-".repeat(50));
console.log("CRMRequest", "req.body");
console.log(req.body);
if(cookies.jwt !== undefined && cookies.jwt !== null)
{
console.log("cookies.jwt");
console.log(cookies.jwt);
var client_jwt_decoded = jwt.verify(cookies.jwt, process.env.JWT_SECRET_CLIENT);
var crm_jwt = jwt.sign(client_jwt_decoded, process.env.JWT_SECRET_CRM, { noTimestamp: true });
console.log("client_jwt_decoded", client_jwt_decoded);
console.log("crm_jwt", crm_jwt);
console.log("path", path);
console.log("params", { ...client_jwt_decoded, ...params });
try
{
await axios.get(path, {
params: { ...client_jwt_decoded, ...params },
headers: {
"Authorization": `Bearer ${ crm_jwt }`,
},
withCredentials: true,
})
.then((crm_response) =>
{
console.log("crm_response for", path);
console.log(crm_response.data);
res.status(200).json(crm_response.data);
})
.catch((error) =>
{
console.error(error);
res.status(500);
});
}
catch(e)
{
console.error(e);
res.status(500);
}
}
else
{
res.status(403);
}
}
}

View File

@ -6,7 +6,7 @@ module.exports = withImages(withFonts(withLess({
images: {
domains: [ 'lk-evo.quickcode.ru', 'wow.evoleasing.ru', 'www.evoleasing.ru', 'lk.evoleasing.ru', 'evoleasing.ru', 'localhost', 'localhost:3000'],
},
reactStrictMode: true,
reactStrictMode: false,
/*
async headers()
{
@ -30,6 +30,11 @@ module.exports = withImages(withFonts(withLess({
async redirects()
{
return [
{
source: '/support',
destination: '/support/faq/',
permanent: false,
},
//{
//source: '/special',
//destination: '/special/with_producer',
@ -57,10 +62,30 @@ module.exports = withImages(withFonts(withLess({
source: "/contract/:number/documents",
destination: "/contract/documents",
},
{
source: "/contract/:number/penalties",
destination: "/contract/penalties",
},
{
source: "/contract/:number/materials",
destination: "/contract/materials",
}
},
{
source: "/contract/:number/events",
destination: "/contract/events",
},
{
source: "/contract/:number/fines",
destination: "/contract/fines",
},
{
source: "/contract/:number/change",
destination: "/contract/change",
},
{
source: "/support/faq",
destination: "/support",
},
//{
//source: "/about/reviews/:page(\\d{1,})",
//destination: "/about/reviews",

View File

@ -0,0 +1,44 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import axios from 'axios';
import { Cookies } from 'react-cookie';
import cookie from 'cookie';
import moment from 'moment';
import jwt from 'jsonwebtoken';
import { cors } from '../../../lib/cors';
export default async function handler(req, res)
{
await cors(req, res);
let { token } = req.body;
if(token !== undefined && token !== null)
{
console.log("API", "offstage", `${ process.env.NEXT_PUBLIC_API_HOST }/api/user/check/`);
await axios.post(`${ process.env.NEXT_PUBLIC_API_HOST }/api/user/check/`, {
token,
})
.then((api_response) =>
{
console.log("RESPONSE");
console.log(api_response.data);
res.status(200).send(api_response.data);
//resolve(api_response.data);
})
.catch((error) =>
{
console.log("error");
console.error(error);
res.status(403).json();
//reject();
});
}
else
{
res.status(404).json();
}
}

View File

@ -0,0 +1,7 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import CRMRequest from '../../../../lib/CRMRequest';
export default async function handler(req, res)
{
await CRMRequest(req, res, `${ process.env.CRM_API_HOST }/lk/add-contract/GetPreCalculations`, { contract_number: req.body.number });
}

View File

@ -0,0 +1,7 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import CRMRequest from '../../../../../lib/CRMRequest';
export default async function handler(req, res)
{
await CRMRequest(req, res, `${ process.env.CRM_API_HOST }/lk/add-contract/CreateCalculation`, { contract_number: req.body.number });
}

View File

@ -0,0 +1,7 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import CRMRequest from '../../../../../lib/CRMRequest';
export default async function handler(req, res)
{
await CRMRequest(req, res, `${ process.env.CRM_API_HOST }/lk/add-contract/GetPreCalculationGraph`, { addcontract_number: req.body.calculation });
}

View File

@ -0,0 +1,7 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import CRMRequest from '../../../../../lib/CRMRequest';
export default async function handler(req, res)
{
await CRMRequest(req, res, `${ process.env.CRM_API_HOST }/lk/add-contract/GetCurrentGraph`, { contract_number: req.body.number });
}

View File

@ -0,0 +1,7 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import CRMRequest from '../../../../lib/CRMRequest';
export default async function handler(req, res)
{
await CRMRequest(req, res, `${ process.env.CRM_API_HOST }/lk/add-contract/GetSignatories`, {});
}

View File

@ -0,0 +1,7 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import CRMRequest from '../../../../lib/CRMRequest';
export default async function handler(req, res)
{
await CRMRequest(req, res, `${ process.env.CRM_API_HOST }/lk/add-contract/GetAvaliableGraphChangeTypes`, { ...{ contract_number: req.body.number }, ...req.body.variants });
}

View File

@ -0,0 +1,51 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import axios from 'axios';
import { Cookies } from 'react-cookie';
import cookie from 'cookie';
import moment from 'moment';
import jwt from 'jsonwebtoken';
import { cors } from '../../../lib/cors';
export default async function handler(req, res)
{
console.log("API", "penalties");
await cors(req, res);
if(req.headers.cookie !== undefined)
{
const cookies = cookie.parse(req.headers?.cookie ? req.headers?.cookie : "");
if(cookies.jwt !== undefined && cookies.jwt !== null)
{
var client_jwt_decoded = jwt.verify(cookies.jwt, process.env.JWT_SECRET_CLIENT);
var crm_jwt = jwt.sign(client_jwt_decoded, process.env.JWT_SECRET_CRM, { noTimestamp: true });
const response = await new Promise((resolve) =>
{
console.log("API", "penalties", `${ process.env.CRM_API_HOST }/lk/Contract/GetPlannedFines`, { contract_number: req.body.number, planned_date: req.body.date });
axios.get(`${ process.env.CRM_API_HOST }/lk/Contract/GetPlannedFines`, {
params: { ...client_jwt_decoded, contract_number: req.body.number, planned_date: req.body.date },
headers: { "Authorization": `Bearer ${ crm_jwt }`, },
withCredentials: true,
})
.then((crm_response) =>
{
console.log("API", "penalties", "crm_response.data", crm_response.data);
resolve(crm_response.data);
})
.catch((error) =>
{
console.error(error);
resolve(error);
});
});
res.status(200).json(response);
}
else
{
res.status(403);
}
}
}

View File

@ -36,7 +36,7 @@ export default async function handler(req, res)
try
{
axios.get(`${ process.env.CRM_API_HOST }/lk/Account/GetContracts/`, {
await axios.get(`${ process.env.CRM_API_HOST }/lk/Account/GetContracts/`, {
params: client_jwt_decoded,
headers: {
"Authorization": `Bearer ${ crm_jwt }`,

View File

@ -10,6 +10,8 @@ export default async function handler(req, res)
{
await cors(req, res);
console.log("API", "events", req.headers);
if(req.headers.cookie !== undefined)
{
const cookies = cookie.parse(req.headers?.cookie ? req.headers?.cookie : "");
@ -19,9 +21,12 @@ export default async function handler(req, res)
var client_jwt_decoded = jwt.verify(cookies.jwt, process.env.JWT_SECRET_CLIENT);
var crm_jwt = jwt.sign(client_jwt_decoded, process.env.JWT_SECRET_CRM, { noTimestamp: true });
console.log("client_jwt_decoded");
console.log(client_jwt_decoded);
try
{
axios.get(`${ process.env.CRM_API_HOST }/lk/Account/GetEvents/`, {
await axios.get(`${ process.env.CRM_API_HOST }/lk/Account/GetEvents/`, {
params: client_jwt_decoded,
headers: {
"Authorization": `Bearer ${ crm_jwt }`,
@ -34,18 +39,22 @@ export default async function handler(req, res)
.catch((error) =>
{
console.error(error);
res.status(500);
res.status(500).send();
});
}
catch(e)
{
console.error(e);
res.status(500);
res.status(500).send();
}
}
else
{
res.status(403);
res.status(403).send();
}
}
else
{
res.status(403).send();
}
}

0
pages/api/events/get.js Normal file
View File

0
pages/api/events/read.js Normal file
View File

View File

@ -8,46 +8,64 @@ import { cors } from '../../../lib/cors';
export default async function handler(req, res)
{
console.log("API\n\n\n\n\n\n\n");
console.log("API", "file", "image");
await cors(req, res);
if(req.headers.cookie !== undefined)
{
console.log("api 1");
const cookies = cookie.parse(req.headers?.cookie ? req.headers?.cookie : "");
if(cookies.jwt !== undefined && cookies.jwt !== null)
{
console.log("api 2");
var client_jwt_decoded = jwt.verify(cookies.jwt, process.env.JWT_SECRET_CLIENT);
var crm_jwt = jwt.sign(client_jwt_decoded, process.env.JWT_SECRET_CRM, { noTimestamp: true });
try
console.log("api 3");
console.log("API", "file", "image", "/file/GetImage", "req.query.id", req.query.id);
await axios.get(`${ process.env.CRM_API_HOST }/file/GetImage`, {
params: { id: req.query.id },
responseType: 'arraybuffer',
headers: {
"Authorization": `Bearer ${ crm_jwt }`,
}
})
.then((crm_response) =>
{
console.log("/lk/GetImage", "req.query.id", req.query.id);
axios.get(`${ process.env.CRM_API_HOST }/lk/GetImage`, {
params: { id: req.query.id },
//responseType: 'arraybuffer',
headers: {
"Authorization": `Bearer ${ crm_jwt }`,
}
})
.then((crm_response) =>
try
{
res.status(200).send(crm_response.data);
})
.catch((error) =>
console.log("crm_response.data");
console.log(crm_response.data);
const base64image = `data:${ crm_response['headers']['content-type'] };base64,${ Buffer.from(crm_response.data, 'binary').toString('base64') }`;
console.log("base64image");
console.log(base64image);
res.status(200).send(base64image);
}
catch(e)
{
console.error(error);
console.error(e);
res.status(500);
});
}
catch(e)
}
})
.catch((error) =>
{
console.error(e);
console.error(error);
res.status(500);
}
});
}
else
{
res.status(403);
}
}
else
{
console.log("WTF?!?!?!!?");
}
}

View File

@ -1,152 +0,0 @@
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 { SpinnerCircular } from "spinners-react";
import { reduxWrapper } from "../../store";
import Header from "../components/Header";
import Footer from "../components/Footer";
import Company from "../components/Company";
import InnerMenu from "../components/Appeals/InnerMenu";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
class ContractPage extends React.Component {
constructor(props) {
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
componentDidMount() {}
render() {
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
console.log("rules", rules);
const types = {
contracts: "Договор",
redemptions: "Выкупные документы",
agreements: "Дополнительное соглашение",
assignments: "Договор цессии",
};
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">Обращение</h1>
</div>
</div>
<div className="aside_container about">
<article className="full">
<div className="new_appeal">
<div className="column full">
<div className="column_text_block">
<p>
<b>Досрочное прекращение срока действия договора лизинга</b>
</p>
<p>
<b>Процедура</b>
</p>
<p>
К каждой теме свободное html поле для миниинструкции
(со ссылками на <a>формы документов</a> и{" "}
<a>документы</a>). Привязка к теме обращения в CRM
</p>
</div>
<div className="column_text_block">
<p>
<b>Документы</b>
</p>
<div className="dosc_list medium-icon">
<div className="row">
<p className="doc_name i-pdf extension">
2021_1655 от 20.04.2021
<span>2021_1655 от 20.04.2021</span>
</p>
</div>
<div className="row">
<p className="doc_name i-pdf extension">
2021_1655 от 20.04.2021
<span>2021_1655 от 20.04.2021</span>
</p>
</div>
</div>
</div>
<button className="button button-blue">Создать обращение</button>
</div>
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
//number: query.number,
number: null,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractPage));

View File

@ -1,245 +0,0 @@
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 { SpinnerCircular } from "spinners-react";
import { reduxWrapper } from "../../store";
import Header from "../components/Header";
import Footer from "../components/Footer";
import Company from "../components/Company";
import InnerMenu from "../components/Appeals/InnerMenu";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
class ContractPage extends React.Component {
constructor(props) {
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
componentDidMount() {}
render() {
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
console.log("rules", rules);
const types = {
contracts: "Договор",
redemptions: "Выкупные документы",
agreements: "Дополнительное соглашение",
assignments: "Договор цессии",
};
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 />
</div>
<div className="aside_container about">
<InnerMenu number={number} {...this.props} />
<article>
<div className="appeal_list">
<div className="appeal_item">
<div className="item_header">
<p>
Номер обращения: <b>123 от 13.04.2022</b>
</p>
<p>
Отвественный ОРК: <b>Иванов И.И.</b>
</p>
<p>
Договор: <b>2021_1655, 2021_1655</b>
</p>
<div className="status">Активное</div>
</div>
<div className="item_body">
<div className="item_text">
<p>
<b>Тема запроса</b>
</p>
<p>
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент
</p>
</div>
<div className="item_text">
<p>
<b>Текст ответа ОРК</b>
</p>
<p>
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент
</p>
</div>
</div>
</div>
<div className="appeal_item">
<div className="item_header">
<p>
Номер обращения: <b>123 от 13.04.2022</b>
</p>
<p>
Отвественный ОРК: <b>Иванов И.И.</b>
</p>
<p>
Договор: <b>2021_1655, 2021_1655</b>
</p>
</div>
<div className="item_body">
<div className="item_text">
<p>
<b>Тема запроса</b>
</p>
<p>
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент
</p>
</div>
<div className="item_text">
<p>
<b>Текст ответа ОРК</b>
</p>
<p>
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент
</p>
<div className="dosc_list medium-icon">
<div className="row">
<p className="doc_name i-pdf extension">
2021_1655 от 20.04.2021
<span>2021_1655 от 20.04.2021</span>
</p>
</div>
<div className="row">
<p className="doc_name i-pdf extension">
2021_1655 от 20.04.2021
<span>2021_1655 от 20.04.2021</span>
</p>
</div>
</div>
</div>
</div>
</div>
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
//number: query.number,
number: null,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractPage));

View File

@ -1,258 +0,0 @@
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 { SpinnerCircular } from "spinners-react";
import { reduxWrapper } from "../../store";
import Header from "../components/Header";
import Footer from "../components/Footer";
import Company from "../components/Company";
import InnerMenu from "../components/Appeals/InnerMenu";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
class ContractPage extends React.Component {
constructor(props) {
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
search: "",
};
}
static getDerivedStateFromProps(nextProps, prevState) {
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
componentDidMount() {
if (!this.state.loading && this.props.number !== undefined) {
this.setState({ loading: true }, () => {
getContractInfo({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then((info) => {
console.log("info", info);
getContractRules({
dispatch: this.props.dispatch,
date: moment(info.date, "YYYY-MM-DD").format("DD.MM.YYYY"),
})
.then(() => {})
.catch(() => {});
})
.catch(() => {});
getContractAgreement({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then(() => {
this.setState({ loading: false });
})
.catch(() => {});
});
}
}
render() {
const { loading, date, car, contract_date, agreement, rules, search } =
this.state;
const { number } = this.props;
console.log("rules", rules);
const types = {
contracts: "Договор",
redemptions: "Выкупные документы",
agreements: "Дополнительное соглашение",
assignments: "Договор цессии",
};
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">Обращение</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 />
</div>
<div className="aside_container about">
<InnerMenu number={number} {...this.props} />
<article>
<div className="contract_search">
<form
onSubmit={(event) => {
event.preventDefault();
}}
>
<div className="form_field full">
<input
type="search"
value={search}
placeholder="Поиск"
onChange={(event) => {
this._handle_onChange_search(event.target.value);
}}
/>
</div>
<button
className="button"
disabled={search !== "" ? false : true}
onClick={this._handle_onSearch}
>
Поиск
</button>
</form>
</div>
<div className="list faq-list">
<div className="faq_item">
<p className="item_title">Изменение графика платежей</p>
<div className="dropdown_blocks_list">
<div className="dropdown_block">
<div className="block_header">
<p>
Как изменить график платежей по договору лизинга?
</p>
<button></button>
</div>
<div className="block_body">
<p>Lorem</p>
</div>
</div>
</div>
</div>
<div className="faq_item">
<p className="item_title">Переуступка прав</p>
<div className="dropdown_blocks_list">
<div className="dropdown_block">
<div className="block_header">
<p>Как получить консультацию по Цессии?</p>
<button></button>
</div>
<div className="block_body">
<p>Lorem</p>
</div>
</div>
<div className="dropdown_block">
<div className="block_header">
<p>
Оформление переуступки прав и обязательств по
договору лизинга
</p>
<button></button>
</div>
<div className="block_body">
<p>Lorem</p>
</div>
</div>
</div>
</div>
<div className="faq_item">
<p className="item_title">
Досрочное прекращение срока действия договора лизинга
</p>
<div className="dropdown_blocks_list">
<div className="dropdown_block">
<div className="block_header">
<p>
Процедура досрочного прекращения срока действия
договора лизинга
</p>
<button></button>
</div>
<div className="block_body">
<p>Lorem</p>
</div>
</div>
</div>
</div>
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
//number: query.number,
number: null,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractPage));

View File

@ -1,220 +0,0 @@
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 { SpinnerCircular } from "spinners-react";
import { reduxWrapper } from "../../store";
import Header from "../components/Header";
import Footer from "../components/Footer";
import Company from "../components/Company";
import InnerMenu from "../components/Appeals/InnerMenu";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
class ContractPage extends React.Component {
constructor(props) {
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
componentDidMount() {}
render() {
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
console.log("rules", rules);
const types = {
contracts: "Договор",
redemptions: "Выкупные документы",
agreements: "Дополнительное соглашение",
assignments: "Договор цессии",
};
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">Новое обращение</h1>
</div>
<Company />
</div>
<div className="aside_container about">
<article className="full">
<div className="new_appeal">
<div className="column">
<div className="dropdown_blocks_list appeal_list">
<div className="appeal_item dropdown_block">
<div className="block_header">
<p>
Процедура досрочного прекращения срока действия
договора лизинга
</p>
<button className="rotate"></button>
</div>
</div>
<div className="appeal_item dropdown_block">
<div className="block_header">
<p>
Как изменить график платежей по договору лизинга?
</p>
<button className="rotate"></button>
</div>
</div>
<div className="appeal_item dropdown_block">
<div className="block_header">
<p>Как получить консультацию по Цессии?</p>
<button className="rotate"></button>
</div>
</div>
<div className="appeal_item dropdown_block open">
<div className="block_header">
<p>
Оформление переуступки прав и обязательств по
договору лизинга
</p>
<button className="rotate"></button>
</div>
</div>
</div>
</div>
<div className="column">
<div className="column_text_block">
<p>
<b>Процедура</b>
</p>
<p>
К каждой теме свободное html поле для миниинструкции
(со ссылками на <a>формы документов</a> и{" "}
<a>документы</a>). Привязка к теме обращения в CRM
</p>
</div>
<div className="column_text_block">
<p>
<b>Документы</b>
</p>
<div className="dosc_list medium-icon">
<div className="row">
<p className="doc_name i-pdf extension">
2021_1655 от 20.04.2021
<span>2021_1655 от 20.04.2021</span>
</p>
</div>
<div className="row">
<p className="doc_name i-pdf extension">
2021_1655 от 20.04.2021
<span>2021_1655 от 20.04.2021</span>
</p>
</div>
</div>
</div>
<form>
<div className="form_field">
<select>
<option default selected disabled>
Выберите договоры
</option>
<option>Договор 1</option>
</select>
</div>
<div className="form_field">
<input
type="text"
name="name"
placeholder="Ваше ФИО"
/>
</div>
<div className="form_field">
<input type="tel" name="name" placeholder="Телефон" />
</div>
<div className="form_field">
<input type="email" name="name" placeholder="Email" />
</div>
<div className="form_field">
<textarea placeholder="Введите текст запроса"></textarea>
</div>
<div className="file_upload dropzone">
<div className="files"></div>
<div>
<p>Перенесите файлы на экран для быстрой загрузки или выберите файл с компьетра </p>
<label htmlFor="" className="button button-blue">Загрузить файл</label>
</div>
<input type="file" accept="" />
</div>
</form>
</div>
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
//number: query.number,
number: null,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractPage));

View File

@ -22,7 +22,7 @@ class Company extends React.Component
_handleOnClick = () =>
{
const { opened } = this.state;
this.setState({ opened: !opened ? true : false })
//this.setState({ opened: !opened ? true : false })
}
render()
@ -33,10 +33,10 @@ class Company extends React.Component
return (
<div className="right company-dropdown" onClick={ this._handleOnClick }>
<p align="right" className="arrow">
<b>{ company.title }</b><br/>
{company.inn != null && <span>ИНН: { company.inn } </span>}
{company.kpp != null && <span>КПП: { company.kpp }</span>}
<p align="right">{/* className="arrow" */}
<b>{ company.title }</b><br/>
{company.inn != null && <span>ИНН: { company.inn } </span>}
{company.kpp != null && <span>КПП: { company.kpp }</span>}
</p>
<div className={`companies_list ${ opened && "opened" }`}> {/* opened */}

View File

@ -6,71 +6,68 @@ export default class InnerMenu extends React.Component
constructor(props)
{
super(props);
this.state = {
type: undefined
};
this.menuRef = React.createRef();
}
componentDidMount()
{
let l = 0;
let m = 0;
const menu = ["payments", "services", "agreement", "documents", "materials","events","change"];
const hash = this.props.router.asPath.split('#')[1];
this.setState({ type: hash });
}
for(let i in menu)
componentDidUpdate(prevProps, prevState)
{
const hash = this.props.router.asPath.split('#')[1];
if(this.state.type !== hash)
{
if(this.props.router.asPath.indexOf(menu[i]) > -1)
{
m = i;
}
this.setState({ type: hash });
}
for(let i = 0; i < m; i++)
{
l = l + this.menuRef.current.children[i].getBoundingClientRect().width;
}
this.menuRef.current.scrollLeft = l - 50;
}
render()
{
const { number } = this.props;
console.log("Events", "InnerMenu", "this.props.router", this.props.router);
const { type } = this.state;
return (
<aside>
<ul className="aside_nav" ref={ this.menuRef }>
<ul className="aside_nav">
<li>
<Link href={`/contract/${ number }/events`} shallow>
<a className={ this.props.router && this.props.router.asPath.indexOf("events") > -1 ? "active" : "" }>Все события</a>
<Link href={`/events`} shallow>
<a className={ type === undefined ? "active" : "" }>Все события</a>
</Link>
</li>
<li>
<Link href={`/contract/${ number }/change`} shallow>
<a className={ this.props.router && this.props.router.asPath.indexOf("change") > -1 ? "active" : "" }>Ограничения</a>
<Link href={`/events#restrictions`} shallow>
<a className={ type === "restrictions" ? "active" : "" }>Ограничения</a>
</Link>
</li>
<li>
<Link href={`/contract/${ number }/services`} shallow>
<a className={ this.props.router && this.props.router.asPath.indexOf("services") > -1 ? "active" : "" }>Платежи</a>
<Link href={`/events#payments`} shallow>
<a className={ type === "payments" ? "active" : "" }>Платежи</a>
</Link>
</li>
<li>
<Link href={`/contract/${ number }/agreement`} shallow>
<a className={ this.props.router && this.props.router.asPath.indexOf("agreement") > -1 ? "active" : "" }>Дополнительные услуги</a>
<Link href={`/events#additional`} shallow>
<a className={ type === "additional" ? "active" : "" }>Дополнительные услуги</a>
</Link>
</li>
<li>
<Link href={`/contract/${ number }/documents`} shallow>
<a className={ this.props.router && this.props.router.asPath.indexOf("documents") > -1 ? "active" : "" }>Штрафы</a>
<Link href={`/events#fines`} shallow>
<a className={ type === "fines" ? "active" : "" }>Штрафы</a>
</Link>
</li>
<li>
<Link href={`/contract/${ number }/materials`} shallow>
<a className={ this.props.router && this.props.router.asPath.indexOf("materials") > -1 ? "active" : "" }>Банки</a>
<Link href={`/events#finance`} shallow>
<a className={ type === "finance" ? "active" : "" }>Банки</a>
</Link>
</li>
<li>
<Link href={`/contract/${ number }/payments`} shallow>
<a className={ this.props.router && this.props.router.asPath.indexOf("payments") > -1 ? "active" : "" }>ПТС</a>
<Link href={`/events#pts`} shallow>
<a className={ type === "pts" ? "active" : "" }>ПТС</a>
</Link>
</li>
</ul>

View File

@ -0,0 +1,170 @@
import React from "react";
import Link from "next/link";
import moment from 'moment';
import pluralize from 'pluralize-ru';
export default class NotificationMessage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
};
}
render()
{
const { event } = this.props;
switch(event.event_type)
{
case "kasko_prolong":
{
const days_left = moment(event.event_date).diff(moment().startOf("day"), 'days');
return (
<li className="new">
<p className="name"><b>Внимание! { days_left === 0 ? "Сегодня последний день" : `${ pluralize(days_left, "Осталось", "Остался", "Осталось", "Осталось") } ${ days_left } ${ pluralize(days_left, "дней", "день", "дня", "дней") } до` } пролонгации КАСКО по договору { event.contract_number } (полис { event.add_info }). Не забудьте самостоятельно продлить полис КАСКО!</b></p>
{ event.important && (<p className="type">Важное</p>) }
<p className="date">{ event.event_date }</p>
<p className="action">
<Link href={`/contract/${ event.contract_number }/services#insurance`}>
<a>Подробнее</a>
</Link>
</p>
</li>
)
}
case "osago_prolong":
{
const days_left = moment(event.event_date).diff(moment().startOf("day"), 'days');
return (
<li className="new">
<p className="name"><b>Внимание! { days_left === 0 ? "Сегодня последний день" : `${ pluralize(days_left, "Осталось", "Остался", "Осталось", "Осталось") } ${ days_left } ${ pluralize(days_left, "дней", "день", "дня", "дней") } до` } пролонгации ОСАГО по договору { event.contract_number } (полис { event.add_info }). Не забудьте самостоятельно продлить полис ОСАГО!</b></p>
{ event.important && (<p className="type">Важное</p>) }
<p className="date">{ event.event_date }</p>
<p className="action">
<Link href={`/contract/${ event.contract_number }/services#insurance`}>
<a>Подробнее</a>
</Link>
</p>
</li>
)
}
case "fingap_prolong":
{
const days_left = moment(event.event_date).diff(moment().startOf("day"), 'days');
return (
<li className="new">
<p className="name"><b>Внимание! { days_left === 0 ? "Сегодня последний день" : `${ pluralize(days_left, "Осталось", "Остался", "Осталось", "Осталось") } ${ days_left } ${ pluralize(days_left, "дней", "день", "дня", "дней") } до` } пролонгации FinGAP по договору { event.contract_number }. Не забудьте самостоятельно продлить полис FinGAP!</b></p>
{ event.important && (<p className="type">Важное</p>) }
<p className="date">{ event.event_date }</p>
<p className="action">
<Link href={`/contract/${ event.contract_number }/services#insurance`}>
<a>Подробнее</a>
</Link>
</p>
</li>
)
}
case "fine_gibdd":
{
return (
<li className="new">
<p className="name"><b>Внимание! Получен штраф ГИБДД по договору { event.contract_number } на сумму { event.add_info }.</b></p>
{ event.important && (<p className="type">Важное</p>) }
<p className="date">{ event.event_date }</p>
<p className="action">
<Link href={`/contract/${ event.contract_number }/fines`}>
<a>Подробнее</a>
</Link>
</p>
</li>
)
}
case "end_contract":
{
const days_left = moment(event.event_date).diff(moment().startOf("day"), 'days');
return (
<li className="new">
<p className="name"><b>Внимание! { days_left === 0 ? "Сегодня дата" : `${ pluralize(days_left, "Осталось", "Остался", "Осталось", "Осталось") } ${ days_left } ${ pluralize(days_left, "дней", "день", "дня", "дней") } до даты` } окончания договора { event.contract_number }.</b></p>
{ event.important && (<p className="type">Важное</p>) }
<p className="date">{ event.event_date }</p>
<p className="action">
<Link href={`/contract/${ event.contract_number }`}>
<a>Посмотрите порядок оформления выкупа</a>
</Link>
</p>
</li>
)
}
case "graph_change":
{
return (
<li className="new">
<p className="name"><b>Сформировано новое ДС { event.add_info} от { event.event_date } по договору { event.contract_number } от (НЕТ ДАТЫ). Срок подписания (НЕТ ДАТЫ).</b></p>
{ event.important && (<p className="type">Важное</p>) }
<p className="date">{ event.event_date }</p>
<p className="action">
<Link href={`/contract/${ event.contract_number }`}>
<a>Посмотреть дополнительное соглашение</a>
</Link>
</p>
</li>
)
}
}
return null;
{/*}
<li className="new">
<p className="name"><b>Внимание! Просрочена дата возврата СТС по договору: ХХ.ХХ.ХХХХ</b></p>
<p className="date">10.01.2022</p>
<p className="action">
<Link href="/">
<a>Посмотрите порядок возврата СТС</a>
</Link>
&nbsp; или &nbsp;
<Link href="/">
<a>Загрузите скан СТС</a>
</Link>
</p>
</li>
{*/}
{/*}
<li className="new">
<p className="name"><b>Внимание! Просрочена дата возврата СТС по договору: ХХ.ХХ.ХХХХ</b></p>
<p className="date">10.01.2022</p>
<p className="action">
<Link href="/">
<a>Посмотрите порядок возврата СТС</a>
</Link>
&nbsp; или &nbsp;
<Link href="/">
<a>Загрузите скан СТС</a>
</Link>
</p>
</li>
{*/}
{/*}
<li className="new">
<p className="name">Внимание! Осталось ХХ дней до пролонгации КАСКО по договору ХХХХ: ХХ.ХХ.ХХХХ. Не забудьте самостоятельно продлить полис ОСАГО</p>
<p className="date">10.01.2022</p>
<p className="action">
<Link href="/">
<a>Подробнее</a>
</Link>
</p>
</li>
{*/}
}
}

View File

@ -1,8 +1,7 @@
import React from "react";
import Link from "next/link";
import moment from 'moment';
import pluralize from 'pluralize-ru';
import NotificationMessage from "../../Events/NotificationMessage";
export default class NotificationsList extends React.Component
{
@ -13,102 +12,6 @@ export default class NotificationsList extends React.Component
};
}
_renderEvent = (event, index) =>
{
switch(event.event_type)
{
case "kasko_prolong":
{
const days_left = moment(event.event_date).diff(moment().startOf("day"), 'days');
return (
<li className="new" key={ index }>
<p className="name"><b>Внимание! { days_left === 0 ? "Сегодня последний день" : `${ pluralize(days_left, "Осталось", "Остался", "Осталось", "Осталось") } ${ days_left } ${ pluralize(days_left, "дней", "день", "дня", "дней") } до` } пролонгации КАСКО по договору { event.contract_number } (полис { event.add_info }). Не забудьте самостоятельно продлить полис КАСКО!</b></p>
<p className="date">{ event.event_date }</p>
<p className="action">
<Link href={`/contract/${ event.contract_number }/services#insurance`}>
<a>Подробнее</a>
</Link>
</p>
</li>
)
}
case "osago_prolong":
{
const days_left = moment(event.event_date).diff(moment().startOf("day"), 'days');
return (
<li className="new" key={ index }>
<p className="name"><b>Внимание! { days_left === 0 ? "Сегодня последний день" : `${ pluralize(days_left, "Осталось", "Остался", "Осталось", "Осталось") } ${ days_left } ${ pluralize(days_left, "дней", "день", "дня", "дней") } до` } пролонгации ОСАГО по договору { event.contract_number } (полис { event.add_info }). Не забудьте самостоятельно продлить полис ОСАГО!</b></p>
<p className="date">{ event.event_date }</p>
<p className="action">
<Link href={`/contract/${ event.contract_number }/services#insurance`}>
<a>Подробнее</a>
</Link>
</p>
</li>
)
}
case "fingap_prolong":
{
const days_left = moment(event.event_date).diff(moment().startOf("day"), 'days');
return (
<li className="new" key={ index }>
<p className="name"><b>Внимание! { days_left === 0 ? "Сегодня последний день" : `${ pluralize(days_left, "Осталось", "Остался", "Осталось", "Осталось") } ${ days_left } ${ pluralize(days_left, "дней", "день", "дня", "дней") } до` } пролонгации FinGAP по договору { event.contract_number }. Не забудьте самостоятельно продлить полис FinGAP!</b></p>
<p className="date">{ event.event_date }</p>
<p className="action">
<Link href={`/contract/${ event.contract_number }/services#insurance`}>
<a>Подробнее</a>
</Link>
</p>
</li>
)
}
}
return null;
{/*}
<li className="new" key={ index }>
<p className="name"><b>Внимание! Просрочена дата возврата СТС по договору: ХХ.ХХ.ХХХХ</b></p>
<p className="date">10.01.2022</p>
<p className="action">
<Link href="/">
<a>Посмотрите порядок возврата СТС</a>
</Link>
&nbsp; или &nbsp;
<Link href="/">
<a>Загрузите скан СТС</a>
</Link>
</p>
</li>
<li className="new">
<p className="name"><b>Внимание! Просрочена дата возврата СТС по договору: ХХ.ХХ.ХХХХ</b></p>
<p className="date">10.01.2022</p>
<p className="action">
<Link href="/">
<a>Посмотрите порядок возврата СТС</a>
</Link>
&nbsp; или &nbsp;
<Link href="/">
<a>Загрузите скан СТС</a>
</Link>
</p>
</li>
<li className="new">
<p className="name">Внимание! Осталось ХХ дней до пролонгации КАСКО по договору ХХХХ: ХХ.ХХ.ХХХХ. Не забудьте самостоятельно продлить полис ОСАГО</p>
<p className="date">10.01.2022</p>
<p className="action">
<Link href="/">
<a>Подробнее</a>
</Link>
</p>
</li>
{*/}
}
render()
{
const { events } = this.props;
@ -117,12 +20,12 @@ export default class NotificationsList extends React.Component
return (
<>
<ul className="list">
{ events.map((event, index) => this._renderEvent(event, index)) }
{ events !== undefined && events !== null && events.slice(0, 5).map((event, index) => <NotificationMessage event={ event } key={ index }/>) }
</ul>
<Link href="/events">
<a className="all">Все события</a>
</Link>
</>
);
)
}
}

View File

@ -11,25 +11,37 @@ class Header extends React.Component
{
super(props);
this.state = {
observer: false,
menuOpened: false,
notificationsOpened: false,
messagesOpened: false,
events: [],
events_loaded: false,
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
observer: nextProps.observer,
events: nextProps.events,
};
}
componentDidMount()
{
console.log("Header", "CDM");
getEvents({ dispatch: this.props.dispatch });
}
componentDidUpdate(prevProps, prevState)
{
if(!prevState.events_loaded)
{
this.setState({ events_loaded: true });
}
}
_getActiveLink = (route) =>
{
if (route === "/") return "Договоры";
@ -126,11 +138,14 @@ class Header extends React.Component
render()
{
const { menuOpened, notificationsOpened, messagesOpened, events } = this.state;
const { observer, menuOpened, notificationsOpened, messagesOpened, events, events_loaded } = this.state;
console.log("events", events);
return (
<header>
{ observer && (
<div style={{ position: "fixed", backgroundColor: "#1C01A9", display: "flex", width: "100%", zIndex: 1, fontSize: "11px", lineHeight: "16px", alignItems: "center", justifyContent: "center", color: "#fff" }}>Сервисный режим</div>
) }
<div className="container">
<Link href={`/`} shallow>
<a className="logo">
@ -203,7 +218,15 @@ class Header extends React.Component
</a>
<div className={`backdrop ${ notificationsOpened && "opened" }`}>
<div className="modal">
<NotificationsList events={ events }/>
{ events_loaded && (
<>
{ events.length > 0 ? (
<NotificationsList events={ events }/>
) : (
<p style={{ paddingBottom: "30px" }}>Нет действующих событий для показа</p>
) }
</>
)}
<button className="close" onClick={ this._handle_onToggleNotifications }>Закрыть</button>
</div>
</div>
@ -230,6 +253,7 @@ class Header extends React.Component
function mapStateToProps(state, ownProps)
{
return {
observer: state.auth.observer,
events: state.events.list,
}
}

View File

@ -0,0 +1,66 @@
import React from "react";
import { SpinnerCircular } from 'spinners-react';
import { getImage } from '../../../actions';
export default class Manager extends React.Component
{
constructor(props)
{
super(props);
this.state = {
photo: undefined,
loading: true,
};
}
componentDidMount()
{
const { company } = this.props;
if(company.manager_photo !== undefined && company.manager_photo !== null && company.manager_photo !== "")
{
getImage({ id: company.manager_photo })
.then((result) =>
{
this.setState({ photo: result, loading: false });
})
}
else
{
this.setState({ photo: null, loading: false });
}
}
render()
{
const { loading, photo, } = this.state;
const { company, } = this.props;
return (
<div className="helpBox">
<div className="avatar" style={{ alignItems: "center", justifyContent: "center", display: "flex", }}>
{ loading ? (
<SpinnerCircular size={24} thickness={51} speed={100} color="rgba(28, 1, 169, 1)" secondaryColor="rgba(236, 239, 244, 1)" />
) : (
<img style={{ width: 62, height: 62, borderRadius: 31 }} src={ photo !== null ? photo : `/assets/images/icons/avatar.svg` } loading="lazy" alt={ company.manager_fio } />
) }
</div>
<div className="content">
<p className="message">Помогу выбрать новый автомобиль</p>
<p className="name">{ company.manager_fio }</p>
<p className="position">{ company.manager_jobtitle }</p>
<div className="info">
<a href={ `mailto:${ company.manager_email }` }>{ company.manager_email }</a>
{ company.manager_mobilephone !== undefined && company.manager_mobilephone !== null && company.manager_mobilephone !== "" && (
<a href={ `tel:+${ company.manager_mobilephone.replace('/[^\d]/m', '') }` }>{ company.manager_mobilephone }</a>
) }
{ company.manager_telegram !== undefined && company.manager_telegram !== null && company.manager_telegram !== "" && (
<a href={ `https://telegram.me/${ company.manager_telegram.replace("@", "") }` } target="_blank">{ `@${ company.manager_telegram.replace("@", "")}` }</a>
) }
</div>
</div>
</div>
)
}
}

329
pages/contract/__change.js Normal file
View File

@ -0,0 +1,329 @@
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 { SpinnerCircular } from "spinners-react";
import Link from "next/link";
import { reduxWrapper } from "../../store";
import Header from "../components/Header";
import Footer from "../components/Footer";
import Company from "../components/Company";
import InnerMenu from "./components/InnerMenu";
import DateInput from "../components/DatePicker";
import SignatoriesList from "./change/components/SignatoriesList";
import CalculationsList from "./change/components/CalculationsList";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
class ChangeGraphicPage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
componentDidMount()
{
if (!this.state.loading && this.props.number !== undefined)
{
this.setState({ loading: true }, () =>
{
getContractInfo({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then((info) =>
{
console.log("info", info);
getContractRules({
dispatch: this.props.dispatch,
date: moment(info.date, "YYYY-MM-DD").format("DD.MM.YYYY"),
})
.then(() => {})
.catch(() => {});
})
.catch(() => {});
getContractAgreement({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then(() =>
{
this.setState({ loading: false });
})
.catch(() => {});
});
}
}
render()
{
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
console.log("rules", rules);
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 />
</div>
<div className="aside_container about">
<InnerMenu number={number} {...this.props} />
<article className="changes">
<div className="block alert">
<p>
Внимание! Существует активное неподписанное дополнительное
соглашение. Расчёт новых изменений невозможен
</p>
<Link href="#">
<a>Подробнее</a>
</Link>
</div>
<div className="block">
<p className="title">Предварительные расчеты</p>
<CalculationsList />
</div>
<div className="block">
<p className="title">
Подписанты
<Link href="">
<a>Добавить подписанта</a>
</Link>
</p>
<SignatoriesList />
</div>
<div className="block">
<p className="title">Варианты изменения графиков</p>
<form>
<div className="form_field">
<input type="checkbox" hidden id="option_1" name="options" />
<label htmlFor="option_1">Изменить дату платежа</label>
<div className="help_tooltip">
<div className="help_icon">
<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 ">
{" "}
{/* opened */}
<div>
<p>Какой-то описательный текст</p>
<p className="button">Закрыть</p>
</div>
</div>
</div>
</div>
<div className="form_field">
<input type="checkbox" hidden id="option_2" name="options" />
<label htmlFor="option_2">
Изменение параметров страхования
</label>
</div>
<div className="form_field">
<input type="checkbox" hidden id="option_3" name="options" />
<label htmlFor="option_3">
Изменение формулировки выкупной платеж
</label>
</div>
<div className="form_field">
<input type="checkbox" hidden id="option_4" name="options"/>
<label htmlFor="option_4">Лизинговые каникулы</label>
</div>
<div className="form_field">
<input type="checkbox" hidden id="option_5" name="options" />
<label htmlFor="option_5">
Изменение кол-ва платежей
</label>
</div>
<div className="form_field">
<input type="checkbox" hidden id="option_6" name="options" />
<label htmlFor="option_6">Изменение суммы платежей</label>
</div>
<div className="form_field">
<input type="checkbox" hidden id="option_7" name="options" />
<label htmlFor="option_7">Досрочный выкуп</label>
</div>
<div className="form_field">
<input type="checkbox" hidden id="option_8" name="options" />
<label htmlFor="option_8">Изменение Лизингополучателя</label>
</div>
<button className="button button-blue" disabled>
Далее
</button>
</form>
</div>
<div className="block">
<p className="title">Варианты изменения графиков</p>
<form className="calc">
<div className="form_field">
<label>Дата платежа</label>
<DateInput placeholder="" id={"date_to"} onChange={ (date) => this.setState({ date_to: date }) } />
</div>
<div className="form_field">
<input type="checkbox" hidden id="fix_pay" name="fix_pay" />
<label htmlFor="fix_pay">
Фиксировать послединий платеж
</label>
<div className="help_tooltip">
<div className="help_icon">
<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 ">
{" "}
{/* opened */}
<div>
<p>Какой-то описательный текст</p>
<p className="button">Закрыть</p>
</div>
</div>
</div>
</div>
<div className="form_field">
<label>Тип каникул</label>
<div className="form_field">
<input type="radio" hidden id="weeekend_type_1" name="weeekend_type" />
<label htmlFor="weeekend_type_1">
Фиксировать послединий платеж
</label>
</div>
<div className="form_field">
<input type="radio" hidden id="weeekend_type_2" name="weeekend_type" />
<label htmlFor="weeekend_type_2">
Фиксировать послединий платеж
</label>
</div>
</div>
<div className="form_field">
<label>Увеличить график на</label>
<select>
<option>1 месяц (37 платеж)</option>
</select>
</div>
<div className="form_field">
<label>Увеличить график на</label>
<input type="number" placeholder="Укажите сумму" />
<div className="help_tooltip">
<div className="help_icon">
<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 ">
{" "}
{/* opened */}
<div>
<p>Какой-то описательный текст</p>
<p className="button">Закрыть</p>
</div>
</div>
</div>
</div>
<div className="btn_group">
<button className="button button-gray">Назад</button>
<button className="button button-blue">Рассчитать график</button>
</div>
</form>
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) =>
{
return {
props: {
//number: query.number,
number: null,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ChangeGraphicPage));

View File

@ -15,238 +15,240 @@ import InnerMenu from "./components/InnerMenu";
import DownloadPdfButton from "../components/DownloadPdfButton";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
class ContractPage extends React.Component {
constructor(props) {
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
class ContractPage extends React.Component
{
constructor(props)
{
super(props);
this.state =
{
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
componentDidMount() {
if (!this.state.loading && this.props.number !== undefined) {
this.setState({ loading: true }, () => {
getContractInfo({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then((info) => {
console.log("info", info);
componentDidMount()
{
if (!this.state.loading && this.props.number !== undefined)
{
this.setState({ loading: true }, () =>
{
getContractInfo({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then((info) => {
console.log("info", info);
getContractRules({
dispatch: this.props.dispatch,
date: moment(info.date, "YYYY-MM-DD").format("DD.MM.YYYY"),
})
.then(() => {})
.catch(() => {});
})
.catch(() => {});
getContractRules({
dispatch: this.props.dispatch,
date: moment(info.date, "YYYY-MM-DD").format("DD.MM.YYYY"),
})
.then(() => {})
.catch(() => {});
})
.catch(() => {});
getContractAgreement({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then(() => {
this.setState({ loading: false });
})
.catch(() => {});
});
}
}
getContractAgreement({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then(() => {
this.setState({ loading: false });
})
.catch(() => {});
});
}
}
render() {
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
render()
{
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
console.log("rules", rules);
console.log("rules", rules);
const types = {
contracts: "Договор",
redemptions: "Выкупные документы",
agreements: "Дополнительное соглашение",
assignments: "Договор цессии",
};
const types = {
contracts: "Договор",
redemptions: "Выкупные документы",
agreements: "Дополнительное соглашение",
assignments: "Договор цессии",
};
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 />
</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="dosc_list medium-icon">
<p className="list_title">К подписанию</p>
<div className="row">
<p className="doc_name i-pdf extension">
Договор
<span style={{ width: "100%" }}>
2021_1655 от 20.04.2021
</span>
</p>
<div className="btn_group">
<a className="button button-blue">
Скачать
</a>
<a className="button button-blue">
Подписать по ЭДО
</a>
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 />
</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="dosc_list medium-icon">
<p className="list_title">К подписанию</p>
<div className="row">
<p className="doc_name i-pdf extension">
Договор
<span style={{ width: "100%" }}>
2021_1655 от 20.04.2021
</span>
</p>
<div className="btn_group">
<a className="button button-blue">
Скачать
</a>
<a className="button button-blue">
Подписать по ЭДО
</a>
</div>
</div>
<p className="list_title">Действующие</p>
{ agreement !== undefined && agreement !== null && agreement.map((document, index) => (
<React.Fragment key={index}>
{ document.documents !== undefined &&
document.documents !== null &&
document.documents.map((file, file_index) =>
{
console.log("file", file);
return (
<div className="row" key={file_index}>
<p
className="doc_name i-pdf extension"
data-format={ file.extension }
>
{ types[ document.type ] }
<span style={{ width: "100%" }}>
{ file.number } от{" "}
{ moment(file.date).format("DD.MM.YYYY") }
</span>
{ file.type !== undefined && (
<span>{file.type}</span>
) }
</p>
<DownloadPdfButton
id={file.url}
filename={`evoleasing_${document.type}_${file.number}_${file.date}.${file.extension}`}
/>
</div>
);
}) }
</React.Fragment>
)) }
{ rules !== undefined && rules !== null && rules.map((document, index) => (
<div className="row" key={index}>
<p className="doc_name i-pdf">
{ document.name }
<span style={{ width: "100%" }}>
Дата вступления в силу: {document.active_from}
</span>
</p>
<DownloadPdfButton
url={`${process.env.NEXT_PUBLIC_MAIN_SITE}${document.url}`}
filename={`${document.filename}.pdf`}
bitrix={true}
/>
</div>
)) }
</div>
) }
</article>
</div>
</div>
</div>
<p className="list_title">Действующие</p>
{agreement !== undefined &&
agreement !== null &&
agreement.map((document, index) => (
<React.Fragment key={index}>
{document.documents !== undefined &&
document.documents !== null &&
document.documents.map((file, file_index) => {
console.log("file", file);
return (
<div className="row" key={file_index}>
<p
className="doc_name i-pdf extension"
data-format={file.extension}
>
{types[document.type]}
<span style={{ width: "100%" }}>
{file.number} от{" "}
{moment(file.date).format("DD.MM.YYYY")}
</span>
{file.type !== undefined && (
<span>{file.type}</span>
)}
</p>
<DownloadPdfButton
id={file.url}
filename={`evoleasing_${document.type}_${file.number}_${file.date}.${file.extension}`}
/>
</div>
);
})}
</React.Fragment>
))}
{rules !== undefined &&
rules !== null &&
rules.map((document, index) => (
<div className="row" key={index}>
<p className="doc_name i-pdf">
{document.name}
<span style={{ width: "100%" }}>
Дата вступления в силу: {document.active_from}
</span>
</p>
<DownloadPdfButton
url={`${process.env.NEXT_PUBLIC_MAIN_SITE}${document.url}`}
filename={`${document.filename}.pdf`}
bitrix={true}
/>
</div>
))}
</div>
)}
</article>
</div>
</div>
</section>
</main>
<Footer />
</React.Fragment>
);
}
</section>
</main>
<Footer />
</React.Fragment>
);
}
}
function mapStateToProps(state, ownProps) {
return {
contract_date: state.contract.date,
date: state.contract.date,
car: state.contract.car,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
function mapStateToProps(state, ownProps)
{
return {
contract_date: state.contract.date,
date: state.contract.date,
car: state.contract.car,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
number: query.number,
},
};
}
(store) =>
async ({ req, res, query }) => {
return {
props: {
number: query.number,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractPage));

View File

@ -1,475 +0,0 @@
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 { SpinnerCircular } from "spinners-react";
import Link from "next/link";
import { reduxWrapper } from "../../store";
import Header from "../components/Header";
import Footer from "../components/Footer";
import Company from "../components/Company";
import InnerMenu from "./components/InnerMenu";
import DateInput from "./../components/DatePicker";
import Feed from "./../components/Feed";
import FeedUsers from "./../components/Feed/users";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
class ContractPage extends React.Component {
constructor(props) {
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
componentDidMount() {
if (!this.state.loading && this.props.number !== undefined) {
this.setState({ loading: true }, () => {
getContractInfo({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then((info) => {
console.log("info", info);
getContractRules({
dispatch: this.props.dispatch,
date: moment(info.date, "YYYY-MM-DD").format("DD.MM.YYYY"),
})
.then(() => {})
.catch(() => {});
})
.catch(() => {});
getContractAgreement({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then(() => {
this.setState({ loading: false });
})
.catch(() => {});
});
}
}
render() {
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
console.log("rules", rules);
const types = {
contracts: "Договор",
redemptions: "Выкупные документы",
agreements: "Дополнительное соглашение",
assignments: "Договор цессии",
};
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 />
</div>
<div className="aside_container about">
<InnerMenu number={number} {...this.props} />
<article className="changes">
<div className="block alert">
<p>
Внимание! Существует активное неподписанное дополнительное
соглашение. Расчёт новых изменений невозможен
</p>
<Link href="#">
<a>Подробнее</a>
</Link>
</div>
<div className="block">
<p className="title">Предварительные расчеты</p>
<Feed />
</div>
<div className="block">
<p className="title">
Подписанты
<Link href="">
<a>Добавить подписанта</a>
</Link>
</p>
<FeedUsers />
</div>
<div className="block">
<p className="title">Варианты изменения графиков</p>
<form>
<div className="form_field">
<input
type="checkbox"
hidden
id="option_1"
name="options"
/>
<label htmlFor="option_1">Изменить дату платежа</label>
<div className="help_tooltip">
<div className="help_icon">
<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 ">
{" "}
{/* opened */}
<div>
<p>Какой-то описательный текст</p>
<p className="button">Закрыть</p>
</div>
</div>
</div>
</div>
<div className="form_field">
<input
type="checkbox"
hidden
id="option_2"
name="options"
/>
<label htmlFor="option_2">
Изменение параметров страхования
</label>
</div>
<div className="form_field">
<input
type="checkbox"
hidden
id="option_3"
name="options"
/>
<label htmlFor="option_3">
Изменение формулировки выкупной платеж
</label>
</div>
<div className="form_field">
<input
type="checkbox"
hidden
id="option_4"
name="options"
/>
<label htmlFor="option_4">Лизинговые каникулы</label>
</div>
<div className="form_field">
<input
type="checkbox"
hidden
id="option_5"
name="options"
/>
<label htmlFor="option_5">
Изменение кол-ва платежей
</label>
</div>
<div className="form_field">
<input
type="checkbox"
hidden
id="option_6"
name="options"
/>
<label htmlFor="option_6">
Изменение суммы платежей
</label>
</div>
<div className="form_field">
<input
type="checkbox"
hidden
id="option_7"
name="options"
/>
<label htmlFor="option_7">Досрочный выкуп</label>
</div>
<div className="form_field">
<input
type="checkbox"
hidden
id="option_8"
name="options"
/>
<label htmlFor="option_8">
Изменение Лизингополучателя
</label>
</div>
<button className="button button-blue" disabled>
Далее
</button>
</form>
</div>
<div className="block">
<p className="title">Варианты изменения графиков</p>
<form className="calc">
<div className="form_field">
<label>Дата платежа</label>
<DateInput
placeholder=""
id={"date_to"}
onChange={(date) => this.setState({ date_to: date })}
/>
</div>
<div className="form_field">
<input
type="checkbox"
hidden
id="fix_pay"
name="fix_pay"
/>
<label htmlFor="fix_pay">
Фиксировать послединий платеж
</label>
<div className="help_tooltip">
<div className="help_icon">
<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 ">
{" "}
{/* opened */}
<div>
<p>Какой-то описательный текст</p>
<p className="button">Закрыть</p>
</div>
</div>
</div>
</div>
<div className="form_field">
<label>Тип каникул</label>
<div className="form_field">
<input
type="radio"
hidden
id="weeekend_type_1"
name="weeekend_type"
/>
<label htmlFor="weeekend_type_1">
Фиксировать послединий платеж
</label>
</div>
<div className="form_field">
<input
type="radio"
hidden
id="weeekend_type_2"
name="weeekend_type"
/>
<label htmlFor="weeekend_type_2">
Фиксировать послединий платеж
</label>
</div>
</div>
<div className="form_field">
<label>Увеличить график на</label>
<select>
<option>1 месяц (37 платеж)</option>
</select>
</div>
<div className="form_field">
<label>Увеличить график на</label>
<input type="number" placeholder="Укажите сумму" />
<div className="help_tooltip">
<div className="help_icon">
<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 ">
{" "}
{/* opened */}
<div>
<p>Какой-то описательный текст</p>
<p className="button">Закрыть</p>
</div>
</div>
</div>
</div>
<div className="btn_group">
<button className="button button-gray">Назад</button>
<button className="button button-blue">
Рассчитать график
</button>
</div>
</form>
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
//number: query.number,
number: null,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractPage));

View File

@ -0,0 +1,86 @@
import React from "react";
import Slider from "react-slick";
function NextArrow(props)
{
const { className, style, onClick } = props;
return (
<button className={ className } style={{ ...style }} onClick={ onClick } >
<svg width={ 8 } height={ 12 } fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="m1 1 6 5-5.25 5" stroke="#fff" strokeWidth={ 2 } strokeLinecap="round" strokeLinejoin="round" />
</svg>
</button>
)
}
function PrevArrow(props)
{
const { className, style, onClick } = props;
return (
<button className={ className } style={{ ...style }} onClick={ onClick } >
<svg width={ 8 } height={ 12 } fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 11 1 6l5.25-5" stroke="#fff" strokeWidth={ 2 } strokeLinecap="round" strokeLinejoin="round" />
</svg>
</button>
)
}
export default class CalculationsList extends React.Component
{
constructor(props)
{
super(props);
this.state = {
company: {},
};
}
_handle_onCalculation = (calculation_id) =>
{
//href={ `/contract/${ number }/change/#${ calculation.addcontract_number }` }
this.props.onCalculation(calculation_id);
}
render()
{
const settings = {
dots: false,
infinite: false,
speed: 500,
slidesToShow: 2,
slidesToScroll: 1,
centerMode: false,
variableWidth: false,
nextArrow: <NextArrow />,
prevArrow: <PrevArrow />,
};
const { number, calculations } = this.props;
return (
<div className="feed">
<div className="feed_list">
<Slider { ...settings }>
{ calculations.map((calculation, index) =>
(
<div className="feed_item" key={ index }>
<p className="item_title">Расчет { calculation.label }</p>
<p className="item_desc">
{ calculation.date_offset_type_comment !== null && (<>{ calculation.date_offset_type_comment }<br/></>) }
{ calculation.number_paydate_comment !== null && (<>{ calculation.number_paydate_comment }<br/></>) }
{ calculation.insurance_price_result_comment !== null && (<>{ calculation.insurance_price_result_comment }<br/></>) }
{ calculation.fix_last_payment_available_comment !== null && (<>{ calculation.fix_last_payment_available_comment }<br/></>) }
{ calculation.period_new_comment !== null && (<>{ calculation.period_new_comment }<br/></>) }
{ calculation.sum_comment !== null && (<>{ calculation.sum_comment }<br/></>) }
</p>
<a className="item_link interactive" onClick={ () => this._handle_onCalculation(calculation.addcontract_number) }>Подробнее</a>
</div>
)) }
</Slider>
</div>
</div>
);
}
}

View File

@ -0,0 +1,311 @@
import React from "react";
import Head from "next/head";
import Image from "next/image";
import moment from "moment";
import 'moment/locale/ru';
import numeral from "numeral";
import { SpinnerCircular } from "spinners-react";
import Link from "next/link";
export default class Comparison extends React.Component
{
constructor(props)
{
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
calculation: null,
today: moment(),
show_previous: false,
mixed_index: 0,
signatories_show_all: false,
};
}
componentDidMount()
{
if(this.props.signer === undefined)
{
if(this.props.signatories !== undefined && this.props.signatories !== null)
{
this._handle_onSigner(this.props.signatories[0].signatoryid);
}
}
const { calculations, calculation_id, } = this.props;
let calculation = null;
for(let i in calculations)
{
if(calculations[i].addcontract_number === calculation_id)
{
calculation = calculations[i];
break;
}
}
this.setState({ calculation : calculation });
}
componentDidUpdate(prevProps, prevState)
{
if(prevProps.signatories === undefined || prevProps.signatories === null)
{
if(this.props.signer === undefined && this.props.signatories !== undefined && this.props.signatories !== null)
{
this._handle_onSigner(this.props.signatories[0].signatoryid);
}
}
}
_handle_onSigner = (signer_id) =>
{
this.props.onSigner(signer_id);
}
_handle_onOptions = () =>
{
this.props.onOptions();
}
_handle_onSignPaper = () =>
{
}
_handle_onSignEDMS = () =>
{
}
_handle_onMixedPayment = (index) =>
{
this.setState({ mixed_index: index });
}
_handle_onShowPrevious = () =>
{
this.setState({ show_previous: true });
}
render()
{
const { calculation, mixed_index, today, show_previous, signatories_show_all } = this.state;
const { number, signer, signatories, current, calculated } = this.props;
return (
<article className="compare">
<div className="compare_top">
<p>
Выбранный(ые) варианты изменения графика
<a className="interactive" onClick={ this._handle_onOptions }>Вернуться к параметрам изменения графика</a>
</p>
<button className="button button-blue">Скачать PDF</button>
</div>
<div className="compare_data">
{ calculation !== undefined && calculation !== null && calculation.fix_last_payment_available_comment !== null && (
<div className="form_field">
<input type="checkbox" hidden id="" name="" checked disabled />
<label htmlFor="">{ calculation.fix_last_payment_available_comment }</label>
</div>
) }
{ calculation !== undefined && calculation !== null && calculation.date_offset_type_comment !== null && (
<div className="form_field">
<input type="checkbox" hidden id="" name="" checked disabled />
<label htmlFor="">{ calculation.date_offset_type_comment }</label>
</div>
) }
{ calculation !== undefined && calculation !== null && calculation.insurance_price_result_comment !== null && (
<div className="form_field">
<p>
{ calculation.insurance_price_result_comment }
</p>
</div>
) }
{ calculation !== undefined && calculation !== null && calculation.number_paydate_comment !== null && (
<div className="form_field">
<p>
{ calculation.number_paydate_comment }
</p>
</div>
) }
{ calculation !== undefined && calculation !== null && calculation.period_new_comment !== null && (
<div className="form_field">
<p>
{ calculation.period_new_comment }
</p>
</div>
) }
{ calculation !== undefined && calculation !== null && calculation.sum_comment !== null && (
<div className="form_field">
<p>
{ calculation.sum_comment }
</p>
</div>
) }
{/*}
<div className="form_field">
<input type="checkbox" hidden id="" name="" checked disabled />
<label htmlFor="">Изменить дату платежа</label>
</div>
<div className="form_field">
<input type="checkbox" hidden id="" name="" checked disabled />
<label htmlFor="">Изменение кол-ва платежей</label>
</div>
<div className="form_field">
<p>
<span>Дата платежа:</span> 1 месяц (37 платежей)
</p>
</div>
<div className="form_field">
<p>
<span>Тип каникул:</span> С увеличением срока
</p>
</div>
{*/}
</div>
<div className="compare_tables">
<div className="compare_table">
<p className="table_title">Текущий график</p>
<div className="table_body" style={{ display: "flex", flexDirection: "column", }}>
<div className="table_row table_header">
<div></div>
<div>Дата лизингового платежа</div>{/* className="sortable" */}
<div>Лизинговый платеж с НДС </div>{/* className="sortable" */}
<div>Сумма досрочного выкупа</div>{/* className="sortable" */}
</div>
{ !show_previous && (
<div className="table_row row-button" style={{ position: "relative", display: "flex" }}>
<button className="button button-gray" onClick={ this._handle_onShowPrevious }>
Показать прошедшие платежи
</button>
</div>
) }
{ current !== undefined &&
current !== null &&
current.map((payment, index) =>
{
if(!show_previous && moment(payment.plandate) < today) { return null; }
return (
<div key={ `current_${ index }` } className="table_row" style={{ display: "flex" }}>
<div>{ payment.name }</div>
<div>{ moment(payment.plandate, "YYYY.MM.DD").format("DD.MM.YYYY") }</div>
<div>{ numeral(payment.sum).format(' ., ') }&nbsp;</div>
<div>{ numeral(payment.early_repayment_sum).format(' ., ') }&nbsp;</div>
</div>
)
})
}
</div>
</div>
<div className="compare_table">
{ calculation !== undefined && calculation !== null && (
<p className="table_title">
Изменения с платежа { calculation.label }
</p>
) }
<div className="table_body" style={{ display: "flex", flexDirection: "column", }}>
<div className="table_row table_header">
<div></div>
<div>Дата лизингового платежа</div>{/* className="sortable" */}
<div>Лизинговый платеж с НДС </div>{/* className="sortable" */}
<div>Сумма досрочного выкупа</div>{/* className="sortable" */}
</div>
{ !show_previous && (
<div className="table_row row-button" style={{ position: "relative", display: "flex" }}>
<button className="button button-gray" onClick={ this._handle_onShowPrevious }>
Показать прошедшие платежи
</button>
</div>
) }
{ calculated !== undefined &&
calculated !== null &&
calculated.map((payment, index) =>
{
if(!show_previous && moment(payment.plandate) < today) { return null; }
return (
<div key={ `current_${ index }` } className="table_row" style={{ display: "flex" }}>
<div>{ payment.name }</div>
<div>{ moment(payment.plandate, "YYYY.MM.DD").format("DD.MM.YYYY") }</div>
<div>{ numeral(payment.sum).format(' ., ') }&nbsp;</div>
<div>{ numeral(payment.early_repayment_sum).format(' ., ') } &nbsp;</div>
</div>
)
})
}
</div>
</div>
<div className="compare_table touchable">
<div className="table_body">
{ !show_previous && (
<button className="button button-gray" style={{ position: "relative" }} onClick={ this._handle_onShowPrevious }>
Показать прошедшие платежи
</button>
) }
{ current !== undefined &&
current !== null &&
calculated !== undefined &&
calculated !== null &&
current.map((payment, index) =>
{
if(!show_previous && moment(payment.plandate) < today) { return null; }
return (
<div key={ `mixed_${ index }` } className={ `table_row ${ index === mixed_index && "opened" }` } onClick={ () => this._handle_onMixedPayment(index) }>
<p className="row_title">Платеж { payment.name }</p>
<div className="table_group">
<div className="table_cell">
<div><span>Текущий график</span> { moment(payment.plandate, "YYYY.MM.DD").format("DD.MM.YYYY") }</div>
<div><span>На сумму</span> { numeral(payment.sum).format(' ., ') }&nbsp;</div>
<div><span>Сумма досрочного выкупа</span> { numeral(payment.early_repayment_sum).format(' ., ') }&nbsp;</div>
</div>
<div className="table_cell">
<div><span>Новый график</span> { calculated[index] !== undefined ? moment(calculated[index].plandate, "YYYY.MM.DD").format("DD.MM.YYYY") : (`-`) }</div>
<div><span>На сумму</span> { calculated[index] !== undefined ? (<>{ numeral(calculated[index].sum).format(' ., ') }&nbsp;₽</>) : (`-`) }</div>
<div><span>Сумма досрочного выкупа</span> { calculated[index] !== undefined ? (<>{ numeral(calculated[index].early_repayment_sum).format(' ., ') }&nbsp;₽</>) : (`-`) }</div>
</div>
</div>
</div>
)
})
}
</div>
</div>
</div>
<div className="compare_suscr">
<p className="block_title">
Подписанты
{ signatories.length > 3 && (
<a className="interactive" onClick={() => { this.setState({ signatories_show_all: true })}}>Все</a>
)}
</p>
<div className="feed static">
{ signatories.slice(0, signatories_show_all ? signatories.length : 3).map((person, index) => (
<div className="feed_item user" key={ person.signatoryid }>
<input type="radio" hidden id={ `user_${ person.signatoryid }` } name={ `user_${ person.signatoryid }` } checked={ person.signatoryid === signer } onChange={ () => this._handle_onSigner(person.signatoryid) }/>
<label htmlFor={ `user_${ person.signatoryid }` }></label>
<img src="/assets/images/icons/avatar.svg" alt="" />
<div>
<p className="item_title">{ `${ person.lastname } ${ person.firstname } ${ person.middlename }` }</p>
<p className="item_desc">{ person.jobtitle }</p>
</div>
</div>
)) }
</div>
</div>
<div className="btn_group">
<button className="button button-blue" onClick={ this._handle_onSignPaper }>
Согласовать и подписать в бумажном виде
</button>
<button className="button button-blue" onClick={ this._handle_onSignEDMS }>
Согласовать и подписать по ЭДО
</button>
</div>
</article>
);
}
}

View File

@ -0,0 +1,28 @@
import React from "react";
import Link from "next/link";
export default class Comparison extends React.Component
{
constructor(props)
{
super(props);
this.state = {
};
}
render()
{
const { number, signer, signatories } = this.props;
return (
<article className="compare">
<div className="compare_message">
<p>
Дополнительное соглашение отправлено на согласование. После согласования документ появится на странице <br />
<Link href={`/contract/${ number }/agreement`}>«Документы по договору» </Link>
</p>
</div>
</article>
);
}
}

View File

@ -0,0 +1,121 @@
import React from "react";
import DateInput from "../../../../components/DatePicker";
export default class Options extends React.Component
{
constructor(props)
{
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
componentDidMount()
{
}
_handle_onBack = (event) =>
{
event.preventDefault();
this.props.onVariants();
}
_handle_onCalculate = (event) =>
{
event.preventDefault();
this.props.onCalculate();
}
render()
{
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
return (
<div className="block">
<p className="title">Параметры опций изменений графика платежей</p>
<form className="calc">
<div className="form_field">
<label>Дата платежа</label>
<DateInput placeholder="" id={"date_to"} onChange={ (date) => this.setState({ date_to: date }) } />
</div>
<div className="form_field">
<input type="checkbox" hidden id="fix_pay" name="fix_pay" />
<label htmlFor="fix_pay">
Фиксировать послединий платеж
</label>
<div className="help_tooltip">
<div className="help_icon">
<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 ">
{" "}
{/* opened */}
<div>
<p>Какой-то описательный текст</p>
<p className="button">Закрыть</p>
</div>
</div>
</div>
</div>
<div className="form_field">
<label>Тип каникул</label>
<div className="form_field">
<input type="radio" hidden id="weeekend_type_1" name="weeekend_type" />
<label htmlFor="weeekend_type_1">
Фиксировать послединий платеж
</label>
</div>
<div className="form_field">
<input type="radio" hidden id="weeekend_type_2" name="weeekend_type" />
<label htmlFor="weeekend_type_2">
Фиксировать послединий платеж
</label>
</div>
</div>
<div className="form_field">
<label>Увеличить график на</label>
<select>
<option>1 месяц (37 платеж)</option>
</select>
</div>
<div className="form_field">
<label>Увеличить график на</label>
<input type="number" placeholder="Укажите сумму" />
<div className="help_tooltip">
<div className="help_icon">
<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 ">
{" "}
{/* opened */}
<div>
<p>Какой-то описательный текст</p>
<p className="button">Закрыть</p>
</div>
</div>
</div>
</div>
<div className="btn_group">
<button className="button button-gray" onClick={ this._handle_onBack }>Назад</button>
<button className="button button-blue" onClick={ this._handle_onCalculate }>Рассчитать график</button>
</div>
</form>
</div>
);
}
}

View File

@ -0,0 +1,75 @@
import React from "react";
import Slider from "react-slick";
function NextArrow(props)
{
const { className, style, onClick } = props;
return (
<button className={ className } style={{ ...style }} onClick={ onClick } >
<svg width={ 8 } height={ 12 } fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="m1 1 6 5-5.25 5" stroke="#fff" strokeWidth={ 2 } strokeLinecap="round" strokeLinejoin="round" />
</svg>
</button>
);
}
function PrevArrow(props)
{
const { className, style, onClick } = props;
return (
<button className={ className } style={{ ...style }} onClick={ onClick } >
<svg width={ 8 } height={ 12 } fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 11 1 6l5.25-5" stroke="#fff" strokeWidth={ 2 } strokeLinecap="round" strokeLinejoin="round" />
</svg>
</button>
);
}
export default class SignatoriesList extends React.Component
{
constructor(props)
{
super(props);
this.state = {
company: {},
};
}
render()
{
const settings = {
dots: false,
infinite: false,
speed: 500,
slidesToShow: 2,
slidesToScroll: 1,
centerMode: false,
variableWidth: false,
nextArrow: <NextArrow />,
prevArrow: <PrevArrow />,
};
const { signatories } = this.props;
return (
<div className="feed">
<div className="feed_list">
<Slider { ...settings }>
{ signatories !== undefined && signatories !== null && signatories.map((signer, index) =>
(
<div className="feed_item user" key={ index }>
<img src="/assets/images/icons/avatar.svg" alt="" />
<div>
<p className="item_title">{`${ signer.lastname } ${ signer.firstname } ${ signer.middlename }`}</p>
<p className="item_desc">{ signer.jobtitle }</p>
</div>
</div>
)) }
</Slider>
</div>
</div>
);
}
}

View File

@ -0,0 +1,96 @@
import React from "react";
import { SpinnerCircular } from "spinners-react";
import DateInput from "../../../../components/DatePicker";
export default class VariantsList extends React.Component
{
constructor(props)
{
super(props);
this.state = {
};
}
componentDidMount()
{
}
_handle_onVariant = (type) =>
{
const { blocked, loading } = this.props;
if(!blocked && !loading)
{
this.props.onVariant(type);
}
}
_checkVariant = (type) =>
{
const { variants } = this.props;
for(let i in variants.types)
{
if(variants.types[i].name === type)
{
if(variants.types[i].disable === true)
{
return true;
}
return false;
}
}
return false;
}
render()
{
const { number, variants_types, selected, blocked, loading } = this.props;
return (
<div className="block" style={{ position: "relative" }}>
<p className="title">Варианты изменения графиков</p>
<div style={ loading ? { opacity: 0.5, } : {} }>
<form>
{ variants_types.map((variant, index) =>
{
const disabled = this._checkVariant(variant.type);
return (
<div className="form_field" key={ index }>
<input type="checkbox" hidden id={ `variant_${ index }` } name="variants" disabled={ disabled } checked={ selected.indexOf(variant.type) > -1 ? true : false } onChange={ () => { this._handle_onVariant(variant.type) } }/>
<label htmlFor={ `variant_${ index }` } className="unselectable"
style={ disabled ? { color: "#A8026B", textDecoration: "line-through", } : {} }>{ variant.title }</label>
<div className="help_tooltip">
<div className="help_icon">
<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 ">
{" "}
{/* opened */}
<div>
<p>{ variant.help }</p>
<p className="button">Закрыть</p>
</div>
</div>
</div>
</div>
)
}) }
<button className="button button-blue" disabled={ blocked || loading ? true : selected.length > 0 ? false : true }>Далее</button>
</form>
</div>
{ 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>
) }
</div>
)
}
}

View File

@ -0,0 +1,415 @@
import React from "react";
import * as ReactDOM from 'react-dom';
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 { SpinnerCircular } from "spinners-react";
import Link from "next/link";
import { reduxWrapper } from "../../../store";
import Header from "../../components/Header";
import Footer from "../../components/Footer";
import Company from "../../components/Company";
import DateInput from "../../components/DatePicker";
import InnerMenu from "./../components/InnerMenu";
import SignatoriesList from "./components/SignatoriesList";
import CalculationsList from "./components/CalculationsList";
import VariantsList from "./components/VariantsList";
import Final from "./components/Final";
import {
getContractInfo,
getContractGraphicChange,
getContractGraphicChangeVariants,
getContractGraphicChangeGetCurrent,
getContractGraphicChangeGetCalculated,
getContractGraphicChangeSignatories,
} from "../../../actions";
import Options from "./components/Options";
import Comparison from "./components/Comparison";
class ChangeGraphicPage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
mode_options: false,
mode_comparison: false,
mode_calculation: false,
mode_final: false,
calculation_id: undefined,
signer: undefined,
signatories: null,
calculations: null,
variants: null,
variants_selected: [],
variants_unavailable: [],
variants_loading: false,
variants_types: [
{ title: "Изменить дату платежа", type: "change_payment_date", help: "Это подсказка по Изменить дату платежа" },
{ title: "Изменение параметров страхования", type: "insurance_change", help: "Это подсказка по Изменение параметров страхования" },
{ title: "Изменение выкупного платежа", type: "last_payment_change", help: "Это подсказка по Изменение формулировки выкупной платеж" },
{ title: "Лизинговые каникулы", type: "date_offset_change", help: "Это подсказка по Лизинговые каникулы" },
{ title: "Изменение кол-ва платежей", type: "contract_term_change", help: "Это подсказка по Изменение кол-ва платежей" },
{ title: "Изменение суммы платежей", type: "sum_pay_change", help: "Это подсказка по Изменение суммы платежей" },
{ title: "Досрочный выкуп", type: "early_redemption_change", help: "Это подсказка по Досрочный выкуп" },
//{ title: "Изменение Лизингополучателя", type: "", help: "Это подсказка по Изменение Лизингополучателя" },
],
options: null,
current: null,
calculated: null,
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
console.log("getDerivedStateFromProps", nextProps);
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
signatories: nextProps.signatories,
calculations: nextProps.calculations,
variants: nextProps.variants,
options: nextProps.options,
current: nextProps.current,
calculated: nextProps.calculated,
};
}
componentDidMount()
{
//
ReactDOM.findDOMNode(this).parentNode.style.height = "100%";
ReactDOM.findDOMNode(this).parentNode.style.display = "flex";
ReactDOM.findDOMNode(this).parentNode.style.flexDirection = "column";
ReactDOM.findDOMNode(this).parentNode.style.justifyContent = "spaceBetween";
ReactDOM.findDOMNode(this).parentNode.style.alignItems = "stretch";
document.documentElement.style.height = "100%";
document.documentElement.style.display = "flex";
document.documentElement.style.flexDirection = "column";
document.body.style.height = "100%";
document.body.style.display = "flex";
document.body.style.flexDirection = "column";
//
console.log("ChangePage", "MOUNT", "document.location.hash", document.location.hash);
if(document.location.hash !== undefined && document.location.hash !== null && document.location.hash !== "")
{
if (!this.state.loading && this.props.number !== undefined)
{
this.setState({ loading: true }, () =>
{
const { dispatch, number } = this.props;
Promise.all([
getContractGraphicChangeCalculationsList({ dispatch, number }),
getContractGraphicChangeSignatories({ dispatch, number }),
getContractGraphicChangeGetCurrent({ dispatch, number }),
getContractGraphicChangeGetCalculated({ dispatch, calculation: document.location.hash.replace("#", "") }),
])
.then(() =>
{
this.setState({ loading: false, mode_calculation: true });
});
});
}
}
else
{
if (!this.state.loading && this.props.number !== undefined)
{
this.setState({ loading: true }, () =>
{
getContractInfo({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then((info) =>
{
getContractGraphicChange({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then(() =>
{
this.setState({ loading: false });
})
.catch(() => {});
})
.catch(() => {});
});
}
}
}
componentWillUnmount()
{
ReactDOM.findDOMNode(this).parentNode.style.height = "unset";
ReactDOM.findDOMNode(this).parentNode.style.display = "unset";
ReactDOM.findDOMNode(this).parentNode.style.flexDirection = "unset";
ReactDOM.findDOMNode(this).parentNode.style.justifyContent = "unset";
ReactDOM.findDOMNode(this).parentNode.style.alignItems = "unset";
document.documentElement.style.height = "unset";
document.documentElement.style.display = "unset";
document.documentElement.style.flexDirection = "unset";
document.body.style.height = "unset";
document.body.style.display = "unset";
document.body.style.flexDirection = "unset";
}
componentDidUpdate(prevProps, prevState)
{
//console.log("ChangePage", "CDM", "document.location.hash", document.location.hash);
if(document.location.hash)
{
}
}
_handle_onVariants = () =>
{
this.setState({ mode_options: false, mode_comparison: false });
}
_handle_onVariantSelect = (type) =>
{
const selected = [ ...this.state.variants_selected ];
if(selected.indexOf(type) > -1)
{
selected.splice(selected.indexOf(type), 1)
}
else
{
selected.push(type);
}
this.setState({ variants_selected: selected, variants_loading: true }, () =>
{
console.log(this.state.variants_selected);
const { variants_selected, variants_types } = this.state;
const variants = {};
for(let i in variants_types)
{
if(variants_selected.indexOf(variants_types[i].type) > -1)
{
variants[ variants_types[i].type ] = true;
}
else
{
variants[ variants_types[i].type ] = false;
}
}
getContractGraphicChangeVariants({ dispatch: this.props.dispatch, number: this.props.number, variants })
.then(() =>
{
this.setState({ variants_loading: false });
});
});
}
_handle_onOptions = () =>
{
this.setState({ mode_options: true, mode_comparison: false });
}
_handle_onSigner = (signer_id) =>
{
this.setState({ signer: signer_id });
}
_handle_onCalculate = () =>
{
this.setState({ mode_options: false, mode_comparison: true });
}
_handle_onCalculation = (calculation_id) =>
{
this.setState({ loading: true, mode_options: false, calculation_id: calculation_id }, () =>
{
const { dispatch, number } = this.props;
Promise.all([
getContractGraphicChangeGetCurrent({ dispatch, number }),
getContractGraphicChangeGetCalculated({ dispatch, calculation: calculation_id }),
])
.then(() =>
{
this.setState({ loading: false, mode_comparison: true, });
});
});
}
render()
{
const { loading, mode_options, mode_comparison, mode_calculation, mode_final, date, car, contract_date, agreement, rules, signer, signatories, calculations, calculation_id, variants, variants_loading, variants_selected, variants_types, variants_unavailable, options, current, calculated, } = this.state;
const { number } = this.props;
console.log("render", "signatories", signatories);
return (
<React.Fragment>
<Head>
<title>ЛК Эволюция автолизинга</title>
<meta name="description" content="ЛК Эволюция автолизинга" />
</Head>
<Header { ...this.props } />
<main style={{ display: "flex", flexDirection: "column", flex: 1 }}>
<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 />
</div>
{ loading ? (
<div className="aside_container about">
<InnerMenu number={ number } { ...this.props } />
<article className="changes">
<div className="container" style={{ display: "flex", alignItems: "center", justifyContent: "center", }}>
<SpinnerCircular size={ 90 } thickness={ 51 } speed={ 100 } color="rgba(28, 1, 169, 1)" secondaryColor="rgba(236, 239, 244, 1)" />
</div>
</article>
</div>
) : (
<>
{ mode_comparison || mode_calculation || mode_final ? (
<>
{ mode_final ? (
<div className="aside_container about">
<Final number={ number }/>
</div>
) : (
<div className="aside_container about">
<Comparison
signer={ signer }
signatories={ signatories }
calculations={ calculations }
calculation_id={ calculation_id }
current={ current }
calculated={ calculated }
onOptions={ this._handle_onOptions } onSigner={ this._handle_onSigner }
/>
</div>
) }
</>
) : (
<div className="aside_container about">
<InnerMenu number={ number } { ...this.props } />
<article className="changes">
{ mode_options ? (
<Options onVariants={ this._handle_onVariants } onCalculate={ this._handle_onCalculate }/>
) : (
<>
{ variants !== null && (
<>
{ variants.enable_addcontract === false ? (
<div className="block alert">
<p>
Внимание! Существует активное неподписанное дополнительное
соглашение. Расчёт новых изменений невозможен
</p>
<Link href={`/contract/${ number }/agreement`}><a>Подробнее</a></Link>
</div>
) : (
<></>
) }
{ calculations !== undefined && calculations !== null && calculations.length > 0 && (
<div className="block">
<p className="title">Предварительные расчеты</p>
<CalculationsList number={ number } calculations={ calculations } onCalculation={ this._handle_onCalculation }/>
</div>
) }
<div className="block">
<p className="title">
Подписанты
<Link href=""><a>Добавить подписанта</a></Link>
</p>
<SignatoriesList signatories={ signatories }/>
</div>
<VariantsList
onOptions={ this._handle_onOptions }
onVariant={ this._handle_onVariantSelect }
variants={ variants }
variants_types={ variants_types }
selected={ variants_selected }
loading={ variants_loading }
blocked={ variants.enable_addcontract === false ? false : false }
/>
{/*}
{ variants.enable_addcontract !== false && (
) }
{*/}
</>
) }
</>
) }
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
signatories: state.contract.change.signatories,
calculations: state.contract.change.calculations,
variants: state.contract.change.variants,
options: state.contract.change.options,
current: state.contract.change.current,
calculated: state.contract.change.calculated,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) =>
{
return {
props: {
number: query.number,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ChangeGraphicPage));

View File

@ -13,504 +13,461 @@ import Footer from "../components/Footer";
import Company from "../components/Company";
import InnerMenu from "./components/InnerMenu";
import DateInput from "./../components/DatePicker";
import Feed from "./../components/Feed";
import FeedUsers from "./../components/Feed/users";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
class ContractPage extends React.Component {
constructor(props) {
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
class ChangeGraphicComparePage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
componentDidMount() {
if (!this.state.loading && this.props.number !== undefined) {
this.setState({ loading: true }, () => {
getContractInfo({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then((info) => {
console.log("info", info);
componentDidMount()
{
if (!this.state.loading && this.props.number !== undefined)
{
this.setState({ loading: true }, () =>
{
getContractInfo({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then((info) =>
{
console.log("info", info);
getContractRules({
dispatch: this.props.dispatch,
date: moment(info.date, "YYYY-MM-DD").format("DD.MM.YYYY"),
})
.then(() => {})
.catch(() => {});
})
.catch(() => {});
getContractRules({
dispatch: this.props.dispatch,
date: moment(info.date, "YYYY-MM-DD").format("DD.MM.YYYY"),
})
.then(() => {})
.catch(() => {});
})
.catch(() => {});
getContractAgreement({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then(() => {
this.setState({ loading: false });
})
.catch(() => {});
});
}
}
getContractAgreement({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then(() =>
{
this.setState({ loading: false });
})
.catch(() => {});
});
}
}
render() {
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
render() {
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
console.log("rules", rules);
console.log("rules", rules);
const types = {
contracts: "Договор",
redemptions: "Выкупные документы",
agreements: "Дополнительное соглашение",
assignments: "Договор цессии",
};
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 />
</div>
<div className="aside_container about">
<article className="compare">
<div className="compare_top">
<p>
Выбранный(ые) варианты изменения графика
<Link href="#">
<a>Вернуться к параметрам изменения графика</a>
</Link>
</p>
<button className="button button-blue">Скачать PDF</button>
</div>
<div className="compare_data">
<div className="form_field">
<input
type="checkbox"
hidden
id=""
name=""
checked
disabled
/>
<label htmlFor="">Изменить дату платежа</label>
</div>
<div className="form_field">
<input
type="checkbox"
hidden
id=""
name=""
checked
disabled
/>
<label htmlFor="">Изменение кол-ва платежей</label>
</div>
<div className="form_field">
<p>
<span>Дата платежа:</span> 1 месяц (37 платежей)
</p>
</div>
<div className="form_field">
<p>
<span>Тип каникул:</span> С увеличением срока
</p>
</div>
</div>
<div className="compare_tables">
<div className="compare_table">
<p className="table_title">Текущий график</p>
<div className="table_body">
<div className="table_row table_header">
<div></div>
<div className="sortable">
Дата лизингового платежа
</div>
<div className="sortable">Лизинговый платеж с НДС </div>
<div className="sortable">Сумма досрочного выкупа</div>
</div>
<div className="table_row row-button">
<button className="button button-gray">
Показать прошедшие платежи
</button>
</div>
<div className="table_row">
<div>14</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>15</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>16</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>17</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>18</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>19</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>20</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
</div>
</div>
<div className="compare_table">
<p className="table_title">
Изменения с платежа ХХ от ХХ.ХХ.ХХХХ
</p>
<div className="table_body">
<div className="table_row table_header">
<div></div>
<div className="sortable">
Дата лизингового платежа
</div>
<div className="sortable">
Лизинговый платеж с НДС
</div>
<div className="sortable">
Сумма досрочного выкупа
</div>
</div>
<div className="table_row row-button">
<button className="button button-gray">
Показать прошедшие платежи
</button>
</div>
<div className="table_row">
<div>14</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>15</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>16</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>17</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>18</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>19</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>20</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
</div>
</div>
<div className="compare_table touchable">
<div className="table_body">
<button className="button button-gray">
Показать прошедшие платежи
</button>
<div className="table_row opened">
<p className="row_title">Платеж 14</p>
<div className="table_group">
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
</div>
</div>
<div className="table_row">
<p className="row_title">Платеж 15</p>
<div className="table_group">
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
</div>
</div>
<div className="table_row">
<p className="row_title">Платеж 15</p>
<div className="table_group">
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
</div>
</div>
<div className="table_row">
<p className="row_title">Платеж 15</p>
<div className="table_group">
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
</div>
</div>
<div className="table_row">
<p className="row_title">Платеж 15</p>
<div className="table_group">
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
</div>
</div>
<div className="table_row">
<p className="row_title">Платеж 15</p>
<div className="table_group">
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="compare_suscr">
<p className="block_title">
Подписанты
<Link href="#">
<a>Все</a>
</Link>
</p>
<div className="feed static">
<div className="feed_item user">
<input type="radio" hidden id="user_1" name="user_1" />
<label htmlFor="user_1"></label>
<img src="/assets/images/icons/avatar.svg" alt="" />
<div>
<p className="item_title">Иванов Иван</p>
<p className="item_desc">Менеджер по продажам</p>
</div>
</div>
<div className="feed_item user">
<input type="radio" hidden id="user_1" name="user_1" />
<label htmlFor="user_1"></label>
<img src="/assets/images/icons/avatar.svg" alt="" />
<div>
<p className="item_title">Иванов Иван</p>
<p className="item_desc">Менеджер по продажам</p>
</div>
</div>
<div className="feed_item user">
<input type="radio" hidden id="user_1" name="user_1" />
<label htmlFor="user_1"></label>
<img src="/assets/images/icons/avatar.svg" alt="" />
<div>
<p className="item_title">Иванов Иван</p>
<p className="item_desc">Менеджер по продажам</p>
</div>
</div>
<div className="feed_item user">
<input type="radio" hidden id="user_2" name="user_2" />
<label htmlFor="user_2"></label>
<img src="/assets/images/icons/avatar.svg" alt="" />
<div>
<p className="item_title">Иванов Иван</p>
<p className="item_desc">Менеджер по продажам</p>
</div>
</div>
<div className="feed_item user">
<input type="radio" hidden id="user_3" name="user_3" />
<label htmlFor="user_3"></label>
<img src="/assets/images/icons/avatar.svg" alt="" />
<div>
<p className="item_title">Иванов Иван</p>
<p className="item_desc">Менеджер по продажам</p>
</div>
</div>
</div>
</div>
<div className="btn_group">
<button className="button button-blue">
Согласовать и подписать в бумажном виде
</button>
<button className="button button-blue">
Согласовать и подписать по ЭДО
</button>
</div>
<div className="compare_message">
<p>
Дополнительное соглашение отправлено на согласование. После согласования документ появится на странице <br />
<Link href="#">«Документы по договору» </Link>
</p>
</div>
</article>
</div>
</div>
</section>
</main>
<Footer />
</React.Fragment>
);
}
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 />
</div>
<div className="aside_container about">
<article className="compare">
<div className="compare_top">
<p>
Выбранный(ые) варианты изменения графика
<Link href="#">
<a>Вернуться к параметрам изменения графика</a>
</Link>
</p>
<button className="button button-blue">Скачать PDF</button>
</div>
<div className="compare_data">
<div className="form_field">
<input type="checkbox" hidden id="" name="" checked disabled />
<label htmlFor="">Изменить дату платежа</label>
</div>
<div className="form_field">
<input type="checkbox" hidden id="" name="" checked disabled />
<label htmlFor="">Изменение кол-ва платежей</label>
</div>
<div className="form_field">
<p>
<span>Дата платежа:</span> 1 месяц (37 платежей)
</p>
</div>
<div className="form_field">
<p>
<span>Тип каникул:</span> С увеличением срока
</p>
</div>
</div>
<div className="compare_tables">
<div className="compare_table">
<p className="table_title">Текущий график</p>
<div className="table_body">
<div className="table_row table_header">
<div></div>
<div className="sortable">
Дата лизингового платежа
</div>
<div className="sortable">Лизинговый платеж с НДС </div>
<div className="sortable">Сумма досрочного выкупа</div>
</div>
<div className="table_row row-button">
<button className="button button-gray">
Показать прошедшие платежи
</button>
</div>
<div className="table_row">
<div>14</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>15</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>16</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>17</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>18</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>19</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>20</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
</div>
</div>
<div className="compare_table">
<p className="table_title">
Изменения с платежа ХХ от ХХ.ХХ.ХХХХ
</p>
<div className="table_body">
<div className="table_row table_header">
<div></div>
<div className="sortable">
Дата лизингового платежа
</div>
<div className="sortable">
Лизинговый платеж с НДС
</div>
<div className="sortable">
Сумма досрочного выкупа
</div>
</div>
<div className="table_row row-button">
<button className="button button-gray">
Показать прошедшие платежи
</button>
</div>
<div className="table_row">
<div>14</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>15</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>16</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>17</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>18</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>19</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
<div className="table_row">
<div>20</div>
<div>21.02.2021</div>
<div>239 724,05</div>
<div>43 079,18</div>
</div>
</div>
</div>
<div className="compare_table touchable">
<div className="table_body">
<button className="button button-gray">
Показать прошедшие платежи
</button>
<div className="table_row opened">
<p className="row_title">Платеж 14</p>
<div className="table_group">
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
</div>
</div>
<div className="table_row">
<p className="row_title">Платеж 15</p>
<div className="table_group">
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
</div>
</div>
<div className="table_row">
<p className="row_title">Платеж 15</p>
<div className="table_group">
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
</div>
</div>
<div className="table_row">
<p className="row_title">Платеж 15</p>
<div className="table_group">
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
</div>
</div>
<div className="table_row">
<p className="row_title">Платеж 15</p>
<div className="table_group">
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
</div>
</div>
<div className="table_row">
<p className="row_title">Платеж 15</p>
<div className="table_group">
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
<div className="table_cell">
<div><span>Текущий график</span> 21.02.2021</div>
<div><span>На сумму</span> 239 724,05</div>
<div><span>Сумма досрочного выкупа</span> 43 079,18</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="compare_suscr">
<p className="block_title">
Подписанты
<Link href="#">
<a>Все</a>
</Link>
</p>
<div className="feed static">
<div className="feed_item user">
<input type="radio" hidden id="user_1" name="user_1" />
<label htmlFor="user_1"></label>
<img src="/assets/images/icons/avatar.svg" alt="" />
<div>
<p className="item_title">Иванов Иван</p>
<p className="item_desc">Менеджер по продажам</p>
</div>
</div>
<div className="feed_item user">
<input type="radio" hidden id="user_1" name="user_1" />
<label htmlFor="user_1"></label>
<img src="/assets/images/icons/avatar.svg" alt="" />
<div>
<p className="item_title">Иванов Иван</p>
<p className="item_desc">Менеджер по продажам</p>
</div>
</div>
<div className="feed_item user">
<input type="radio" hidden id="user_1" name="user_1" />
<label htmlFor="user_1"></label>
<img src="/assets/images/icons/avatar.svg" alt="" />
<div>
<p className="item_title">Иванов Иван</p>
<p className="item_desc">Менеджер по продажам</p>
</div>
</div>
<div className="feed_item user">
<input type="radio" hidden id="user_2" name="user_2" />
<label htmlFor="user_2"></label>
<img src="/assets/images/icons/avatar.svg" alt="" />
<div>
<p className="item_title">Иванов Иван</p>
<p className="item_desc">Менеджер по продажам</p>
</div>
</div>
<div className="feed_item user">
<input type="radio" hidden id="user_3" name="user_3" />
<label htmlFor="user_3"></label>
<img src="/assets/images/icons/avatar.svg" alt="" />
<div>
<p className="item_title">Иванов Иван</p>
<p className="item_desc">Менеджер по продажам</p>
</div>
</div>
</div>
</div>
<div className="btn_group">
<button className="button button-blue">
Согласовать и подписать в бумажном виде
</button>
<button className="button button-blue">
Согласовать и подписать по ЭДО
</button>
</div>
<div className="compare_message">
<p>
Дополнительное соглашение отправлено на согласование. После согласования документ появится на странице <br />
<Link href="#">«Документы по договору» </Link>
</p>
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
function mapStateToProps(state, ownProps)
{
return {
contract_date: state.contract.date,
date: state.contract.date,
car: state.contract.car,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
//number: query.number,
number: null,
},
};
}
(store) =>
async ({ req, res, query }) =>
{
return {
props: {
//number: query.number,
number: null,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractPage));
export default withRouter(connect(mapStateToProps)(ChangeGraphicComparePage));

View File

@ -0,0 +1,99 @@
import React from "react";
import moment from "moment";
import DateInput from "../../../components/DatePicker";
export default class FinesCalculatorForm extends React.Component
{
constructor(props)
{
super(props);
this.state = {
selected_date: moment().toDate(),
valid_date_start: moment().toDate(),
valid_date_end: moment().add(1, "month").toDate(),
fines_calculation_disabled: false,
};
}
componentDidMount()
{
}
componentDidUpdate(prevProps, prevState)
{
}
_handle_onFinesDate_start = (date) =>
{
const {
valid_date_start,
valid_date_end,
} = this.state;
const md = moment(date, "DD.MM.YYYY");
if (md.isValid())
{
if (date >= valid_date_start && date <= valid_date_end)
{
this.setState({
selected_date: date,
fines_calculation_disabled: false,
});
}
else
{
this.setState({
selected_date: date,
fines_calculation_disabled: true,
});
}
}
else
{
this.setState({ fines_calculation_disabled: true });
}
};
_handle_onApply = () =>
{
const { selected_date } = this.state;
this.props.onPenalties(moment(selected_date).format("YYYY.MM.DD"));
}
render()
{
const {
selected_date,
valid_date_start,
valid_date_end,
fines_calculation_disabled,
} = this.state;
return (
<div className="block-column">
<div className="dropdown_block">
<div className="block_header">
<p>Счета-уведомления на пени</p>
</div>
</div>
<div className="block_with_form">
<p>Введите планируемую дату оплаты просроченной задолженности для расчёта пеней</p>
<form className="paymentDateForm">
<div className="form_field">
<DateInput
placeholder="Планируемая дата"
value={ selected_date }
min={ valid_date_start }
max={ valid_date_end }
onChange={ this._handle_onFinesDate_start }
/>
</div>
<button className="button button-blue" disabled={ fines_calculation_disabled } onClick={ this._handle_onApply }>Применить</button>
</form>
</div>
</div>
);
}
}

View File

@ -7,16 +7,20 @@ export default class InnerMenu extends React.Component
{
super(props);
this.menuRef = React.createRef();
this.state = {
menuOpened: false,
count_events: 0,
count_fines: 0,
};
}
_handle_onToggleMenu = () => {
_handle_onToggleMenu = () =>
{
this.setState({
menuOpened: !this.state.menuOpened,
menuOpened: !this.state.menuOpened,
});
};
};
componentDidMount()
{
@ -40,7 +44,8 @@ export default class InnerMenu extends React.Component
this.menuRef.current.scrollLeft = l - 50;
}
_getActiveLink = (route) => {
_getActiveLink = (route) =>
{
if (route.indexOf("/payments/") > -1) return "График платежей";
if (route.indexOf("/change/") > -1) return "Изменить график";
if (route.indexOf("/services") > -1) return "Дополнительные услуги";
@ -48,19 +53,20 @@ export default class InnerMenu extends React.Component
if (route.indexOf("/documents") > -1) return "Закрывающие документы";
if (route.indexOf("/materials") > -1) return "Документы по ФСБУ 25/2018";
if (route.indexOf("/events") > -1) return "События по договору";
if (route.indexOf("/fines") > -1) return "Штрафы ГИБДД";
return null;
};
};
render()
{
const { menuOpened } = this.state;
const { menuOpened, count_events, count_fines } = this.state;
const { number } = this.props;
return (
<aside>
<button className="nav_toggle" onClick={this._handle_onToggleMenu}>
{this.props.router &&
this._getActiveLink(this.props.router.route)}
{ this.props.router && this._getActiveLink(this.props.router.route) }
</button>
<ul className={menuOpened ? "aside_nav open" : "aside_nav"} ref={ this.menuRef }>
<li>
@ -95,7 +101,12 @@ export default class InnerMenu extends React.Component
</li>
<li>
<Link href={`/contract/${ number }/events`} shallow>
<a className={ this.props.router && this.props.router.asPath.indexOf("events") > -1 ? "active" : "" }>События по договору <span>3</span></a>
<a className={ this.props.router && this.props.router.asPath.indexOf("events") > -1 ? "active" : "" }>События по договору { count_events > 0 && (<span>{ count_events }</span>) }</a>
</Link>
</li>
<li>
<Link href={`/contract/${ number }/fines`} shallow>
<a className={ this.props.router && this.props.router.asPath.indexOf("fines") > -1 ? "active" : "" }>Штрафы ГИБДД{ count_fines > 0 && (<span>{ count_fines }</span>) }</a>
</Link>
</li>
</ul>

File diff suppressed because it is too large Load Diff

View File

@ -13,186 +13,156 @@ import Footer from "../components/Footer";
import Company from "../components/Company";
import InnerMenu from "./components/InnerMenu";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
import NotificationMessage from "../components/Events/NotificationMessage";
class ContractPage extends React.Component {
constructor(props) {
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
import { getContractInfo, getFilteredEvents } from "../../actions";
static getDerivedStateFromProps(nextProps, prevState) {
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
class ContractPage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
events_loaded: false,
filtered: undefined,
loading: true,
};
}
componentDidMount() {
if (!this.state.loading && this.props.number !== undefined) {
this.setState({ loading: true }, () => {
getContractInfo({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then((info) => {
console.log("info", info);
static getDerivedStateFromProps(nextProps, prevState)
{
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
events_loaded: nextProps.events_loaded,
filtered: nextProps.filtered,
};
}
getContractRules({
dispatch: this.props.dispatch,
date: moment(info.date, "YYYY-MM-DD").format("DD.MM.YYYY"),
})
.then(() => {})
.catch(() => {});
})
.catch(() => {});
componentDidMount()
{
getContractInfo({ dispatch: this.props.dispatch, number: this.props.number });
getContractAgreement({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then(() => {
this.setState({ loading: false });
})
.catch(() => {});
});
}
}
if(this.state.events_loaded)
{
getFilteredEvents({ dispatch: this.props.dispatch, contract: this.props.number });
}
}
render() {
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
componentDidUpdate(prevProps, prevState)
{
if(this.state.events_loaded && !prevState.events_loaded)
{
getFilteredEvents({ dispatch: this.props.dispatch, contract: this.props.number });
}
}
console.log("rules", rules);
render()
{
const { loading, date, car, contract_date, events_loaded, filtered, } = this.state;
const { number } = this.props;
const types = {
contracts: "Договор",
redemptions: "Выкупные документы",
agreements: "Дополнительное соглашение",
assignments: "Договор цессии",
};
//console.log("rules", rules);
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 />
</div>
<div className="aside_container about">
<InnerMenu number={number} {...this.props} />
<article>
<ul className="list events-list">
<li className="new">
<p className="name">
<b>
Внимание! Просрочена дата возврата СТС по договору:
ХХ.ХХ.ХХХХ
</b>
</p>
<p className="type">Важное</p>
<p className="date">10.01.2022</p>
<p className="action">
<a href="">Посмотрите порядок возврата СТС</a>&nbsp; или
&nbsp;<a href="">Загрузите скан СТС</a>
</p>
</li>
<li className="new">
<p className="name">
<b>
Внимание! Просрочена дата возврата СТС по договору:
ХХ.ХХ.ХХХХ
</b>
</p>
<p className="date">10.01.2022</p>
<p className="action">
<a href="">Посмотрите порядок возврата СТС</a>&nbsp; или
&nbsp;<a href="">Загрузите скан СТС</a>
</p>
</li>
<li className="new">
<p className="name">
Внимание! Осталось ХХ дней до пролонгации КАСКО по
договору ХХХХ: ХХ.ХХ.ХХХХ. Не забудьте самостоятельно
продлить полис ОСАГО
</p>
<p className="date">10.01.2022</p>
<p className="action">
<a href="">Подробнее</a>
</p>
</li>
</ul>
</article>
</div>
</div>
</section>
</main>
<Footer />
</React.Fragment>
);
}
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 />
</div>
<div className="aside_container about">
<InnerMenu number={ number } { ...this.props } />
<article>
{ filtered !== undefined ? (
<>
{ filtered.length > 0 ? (
<ul className="list events-list">
{ filtered.map((event, index) => (
<NotificationMessage event={ event } key={ index }/>
)) }
</ul>
) : (
<p>Нет событий по данному договору.</p>
) }
</>
) : (
<div className="container" style={{ display: "flex", alignItems: "center", justifyContent: "center", }}>
<SpinnerCircular size={ 90 } thickness={ 51 } speed={ 100 } color="rgba(28, 1, 169, 1)" secondaryColor="rgba(236, 239, 244, 1)" />
</div>
) }
{/*}
<li className="new">
<p className="name"><b>Внимание! Просрочена дата возврата СТС по договору: ХХ.ХХ.ХХХХ</b></p>
<p className="type">Важное</p>
<p className="date">10.01.2022</p>
<p className="action">
<a href="">Посмотрите порядок возврата СТС</a>&nbsp; или
&nbsp;<a href="">Загрузите скан СТС</a>
</p>
</li>
<li className="new">
<p className="name"><b>Внимание! Просрочена дата возврата СТС по договору: ХХ.ХХ.ХХХХ</b></p>
<p className="date">10.01.2022</p>
<p className="action">
<a href="">Посмотрите порядок возврата СТС</a>&nbsp; или
&nbsp;<a href="">Загрузите скан СТС</a>
</p>
</li>
<li className="new">
<p className="name">Внимание! Осталось ХХ дней до пролонгации КАСКО по договору ХХХХ: ХХ.ХХ.ХХХХ. Не забудьте самостоятельно продлить полис ОСАГО</p>
<p className="date">10.01.2022</p>
<p className="action">
<a href="">Подробнее</a>
</p>
</li>
{*/}
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
function mapStateToProps(state, ownProps)
{
return {
contract_date: state.contract.date,
date: state.contract.date,
car: state.contract.car,
events_loaded: state.events.loaded,
filtered: state.events.filtered,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
//number: query.number,
number: null,
},
};
(store) =>
async ({ req, res, query }) =>
{
return {
props: {
number: query.number,
}
}
}
);

View File

@ -1,173 +0,0 @@
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 { SpinnerCircular } from "spinners-react";
import Link from "next/link";
import { reduxWrapper } from "../../store";
import Header from "../components/Header";
import Footer from "../components/Footer";
import Company from "../components/Company";
import InnerMenu from "./components/InnerMenu";
import DateInput from "./../components/DatePicker";
import Feed from "./../components/Feed";
import FeedUsers from "./../components/Feed/users";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
class ContractPage extends React.Component {
constructor(props) {
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
componentDidMount() {
if (!this.state.loading && this.props.number !== undefined) {
this.setState({ loading: true }, () => {
getContractInfo({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then((info) => {
console.log("info", info);
getContractRules({
dispatch: this.props.dispatch,
date: moment(info.date, "YYYY-MM-DD").format("DD.MM.YYYY"),
})
.then(() => {})
.catch(() => {});
})
.catch(() => {});
getContractAgreement({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then(() => {
this.setState({ loading: false });
})
.catch(() => {});
});
}
}
render() {
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
console.log("rules", rules);
const types = {
contracts: "Договор",
redemptions: "Выкупные документы",
agreements: "Дополнительное соглашение",
assignments: "Договор цессии",
};
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={{ alignItems: "center", flexWrap: "wrap" }}>
<button className="back">Назад</button>
<h1 className="section_title">Расчет планируемых пени</h1>
</div>
</div>
<div className="aside_container about">
<article className="fine">
<div className="fine_block">
<div className="fine_col">
<p>
<span>Пени на дату</span>
10.04.2022
</p>
</div>
<div className="fine_col">
<p>
Февраль
<span>28,11 </span>
</p>
<p>
Февраль
<span>1520,20 </span>
</p>
<p>
Февраль
<span>28,11 </span>
</p>
<p>
<span>ИТОГО:</span>
<span>2322,46 </span>
</p>
</div>
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
//number: query.number,
number: null,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractPage));

687
pages/contract/fines.js Normal file
View File

@ -0,0 +1,687 @@
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>&nbsp;</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(" ., ")}&nbsp;
</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>&nbsp;</p>
</div>
</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 !== null
? car.vin_number
: "без VIN номера"
}`
: "" }
</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._renderDocuments(
documents.billfines,
"billfines"
)}
{this._renderFines(documents.fines, "fines")}
</>
) : null}
<div className="block-column">
<div className="dropdown_block ">
<div className="block_header">
<p>Счета-уведомления на пени</p>
</div>
</div>
<div className="block_with_form">
<p>Введите планируемую дату оплаты просроченной задолженности для расчёта пеней</p>
<form className="paymentDateForm">
<div className="form_field">
<DateInput
placeholder="Планируемая дата"
value={period_date_start}
min={valid_date_start}
max={valid_date_end}
onChange={this._handle_onPeriodDate_start}
/>
</div>
<button className="button button-blue">Применить</button>
</form>
</div>
</div>
</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>
{*/
}

View File

@ -95,6 +95,11 @@ class ContractSchedulePage extends React.Component
const { payments, avans, date, car, full, opened, loading } = this.state;
const { number } = this.props;
console.log(".".repeat(50));
console.log("this.state", this.state);
console.log("this.props", this.props);
console.log(".".repeat(50));
console.log("RENDER", "payments");
console.log(payments);
@ -133,33 +138,25 @@ class ContractSchedulePage extends React.Component
<div className="aside_container about">
<InnerMenu number={ number } { ...this.props }/>
<article>
{ parseInt(avans, 10) > 0 && (
<div className="payments_actions">
<div className="avans">
<p>Сумма авансовых поступлений по договору: <span style={{ whiteSpace: "nowrap" }}>{ numeral(avans).format(' ., ') }&nbsp;</span></p>
</div>
</div>
) }
{/* Вариант 1 */}
<div className="payments_actions">
<div>
<p>Счёт на основной долг 1: 45 000 </p>
<div className="payments_actions">
<div style={{ border: "solid 1px red" }}>
<p>Счёт на основной долг 1: 000 </p>
<button className="button button-blue">Скачать счет</button>
</div>
<div>
<p><span>Пени:</span> 45 000 </p>
<div style={{ border: "solid 1px red" }}>
<p><span>Пени:</span> 000 </p>
<button className="button button-blue">Скачать счет</button>
<button className="button button-blue">Рассчитать пени</button>
</div>
</div>
{/* Вариант 2 */}
<div className="avans"><p>Сумма авансовых поступлений по договору: <span style={{ whiteSpace: "nowrap" }}>{ numeral(avans).format(' ., ') }&nbsp;</span></p></div>
{/* Вариант 3 */}
<div className="payments_actions">
<div className="avans"><p>Сумма авансовых поступлений по договору: <span style={{ whiteSpace: "nowrap" }}>{ numeral(avans).format(' ., ') }&nbsp;</span></p></div>
<div>
<p><span>Пени:</span> 45 000 </p>
<button className="button button-blue">Скачать счет</button>
</div>
</div>
<div className="contract_table schedule">
<div className="table_row table_header">
<div className="table_cell"> платежа</div>
@ -280,7 +277,8 @@ function mapStateToProps(state, ownProps)
}
}
export const getServerSideProps = reduxWrapper.getServerSideProps(store =>
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) =>
{
return {

View File

@ -135,7 +135,8 @@ function mapStateToProps(state, ownProps)
}
}
export const getServerSideProps = reduxWrapper.getServerSideProps(store =>
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) =>
{
return {

216
pages/contract/penalties.js Normal file
View File

@ -0,0 +1,216 @@
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 { SpinnerCircular } from "spinners-react";
import Link from "next/link";
import { reduxWrapper } from "../../store";
import Header from "../components/Header";
import Footer from "../components/Footer";
import Company from "../components/Company";
import InnerMenu from "./components/InnerMenu";
import DateInput from "../components/DatePicker";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
class ContractPage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
componentDidMount()
{
if(!this.state.loading && this.props.number !== undefined)
{
this.setState({ loading: true }, () =>
{
getContractInfo({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then((info) =>
{
console.log("info", info);
getContractRules({
dispatch: this.props.dispatch,
date: moment(info.date, "YYYY-MM-DD").format("DD.MM.YYYY"),
})
.then(() => {})
.catch(() => {});
})
.catch(() => {});
getContractAgreement({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then(() =>
{
this.setState({ loading: false });
})
.catch(() => {});
});
}
document.documentElement.style.height = "100%";
document.documentElement.style.display = "flex";
document.documentElement.style.flexDirection = "column";
document.body.style.height = "100%";
document.body.style.display = "flex";
document.body.style.flexDirection = "column";
}
componentWillUnmount()
{
document.documentElement.style.height = "unset";
document.documentElement.style.display = "unset";
document.documentElement.style.flexDirection = "unset";
document.body.style.height = "unset";
document.body.style.display = "unset";
document.body.style.flexDirection = "unset";
}
render()
{
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
console.log("rules", rules);
const types = {
contracts: "Договор",
redemptions: "Выкупные документы",
agreements: "Дополнительное соглашение",
assignments: "Договор цессии",
};
return (
<React.Fragment style={{ height: "100%", display: "flex", flexDirection: "column", justifyContent: "spaceBetween", alignItems: "stretch" }}>
<Head>
<title>ЛК Эволюция автолизинга</title>
<meta name="description" content="ЛК Эволюция автолизинга"/>
</Head>
<Header { ...this.props }/>
<main style={{ height: "100%", display: "flex", flexDirection: "column" }}>
<section>
<div className="clear"></div>
<div className="container">
<div className="title_wrapper">
<div className="left" style={{ alignItems: "center", flexWrap: "wrap", alignItems: "flex-start" }}>
<button className="back">Назад</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>
10.04.2022
</p>
</div>
<div className="fine_col">
<p>
Февраль
<span>28,11 </span>
</p>
<p>
Февраль
<span>1520,20 </span>
</p>
<p>
Февраль
<span>28,11 </span>
</p>
<p>
<span>ИТОГО:</span>
<span>2322,46 </span>
</p>
</div>
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
number: query.number,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractPage));

View File

@ -368,7 +368,8 @@ function mapStateToProps(state, ownProps)
}
}
export const getServerSideProps = reduxWrapper.getServerSideProps(store =>
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) =>
{
return {

View File

@ -13,198 +13,203 @@ import Footer from "./components/Footer";
import Company from "./components/Company";
import InnerMenu from "./components/Events/InnerMenu";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../actions";
import NotificationMessage from "./components/Events/NotificationMessage";
class ContractPage extends React.Component {
constructor(props) {
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
search: ""
};
}
import { getFilteredEvents } from "../actions";
static getDerivedStateFromProps(nextProps, prevState) {
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
class EventsPage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
events: [],
events_loaded: false,
filtered: undefined,
type: undefined,
loading: false,
search: ""
};
}
componentDidMount() {
if (!this.state.loading && this.props.number !== undefined) {
this.setState({ loading: true }, () => {
getContractInfo({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then((info) => {
console.log("info", info);
static getDerivedStateFromProps(nextProps, prevState)
{
return {
events: nextProps.events,
events_loaded: nextProps.events_loaded,
filtered: nextProps.filtered,
};
}
getContractRules({
dispatch: this.props.dispatch,
date: moment(info.date, "YYYY-MM-DD").format("DD.MM.YYYY"),
})
.then(() => {})
.catch(() => {});
})
.catch(() => {});
componentDidMount()
{
}
getContractAgreement({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then(() => {
this.setState({ loading: false });
})
.catch(() => {});
});
}
}
componentDidUpdate(prevProps, prevState)
{
const hash = this.props.router.asPath.split('#')[1];
if(this.state.type !== hash)
{
this.setState({ type: hash }, () =>
{
this._filterEvents();
});
}
}
render() {
const { loading, date, car, contract_date, agreement, rules, search } = this.state;
const { number } = this.props;
_handle_onChange_search = (value) =>
{
this.setState({ search: value });
}
console.log("rules", rules);
_handle_onSearch = () =>
{
this._filterEvents();
}
const types = {
contracts: "Договор",
redemptions: "Выкупные документы",
agreements: "Дополнительное соглашение",
assignments: "Договор цессии",
};
_filterEvents = () =>
{
console.log("_filterEvents");
const { type, search } = this.state;
getFilteredEvents({ dispatch: this.props.dispatch, type, search });
}
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">События</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 />
</div>
<div className="aside_container about">
<InnerMenu number={number} {...this.props} />
<article>
<div className="contract_search">
<form onSubmit={ (event) => { event.preventDefault(); } }>
<div className="form_field full">
<input type="search" value={ search } placeholder="Поиск" onChange={ (event) => {
this._handle_onChange_search(event.target.value);
} }/>
</div>
<button className="button" disabled={ search !== "" ? false : true } onClick={ this._handle_onSearch }>Поиск</button>
</form>
render()
{
const { loading, search, events, events_loaded, filtered } = this.state;
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">События</h1>
</div>
<Company />
</div>
<ul className="list events-list">
<li className="new">
<p className="name">
<b>
Внимание! Просрочена дата возврата СТС по договору:
ХХ.ХХ.ХХХХ
</b>
</p>
<p className="type">Важное</p>
<p className="date">10.01.2022</p>
<p className="action">
<a href="">Посмотрите порядок возврата СТС</a>&nbsp; или
&nbsp;<a href="">Загрузите скан СТС</a>
</p>
</li>
<li className="new">
<p className="name">
<b>
Внимание! Просрочена дата возврата СТС по договору:
ХХ.ХХ.ХХХХ
</b>
</p>
<p className="date">10.01.2022</p>
<p className="action">
<a href="">Посмотрите порядок возврата СТС</a>&nbsp; или
&nbsp;<a href="">Загрузите скан СТС</a>
</p>
</li>
<li className="new">
<p className="name">
Внимание! Осталось ХХ дней до пролонгации КАСКО по
договору ХХХХ: ХХ.ХХ.ХХХХ. Не забудьте самостоятельно
продлить полис ОСАГО
</p>
<p className="date">10.01.2022</p>
<p className="action">
<a href="">Подробнее</a>
</p>
</li>
</ul>
</article>
</div>
</div>
</section>
</main>
<Footer />
</React.Fragment>
);
}
<div className="aside_container about">
<InnerMenu { ...this.props }/>
<article>
<div className="contract_search">
<form onSubmit={ (event) => { event.preventDefault(); } }>
<div className="form_field full">
<input type="search" value={ search } placeholder="Поиск" onChange={ (event) => {
this._handle_onChange_search(event.target.value);
} }/>
</div>
<button className="button" disabled={ search !== "" ? false : true } onClick={ this._handle_onSearch }>Поиск</button>
</form>
</div>
{ events_loaded && (
<>
{ filtered !== undefined ? (
<>
{ filtered.length > 0 ? (
<ul className="list events-list">
{ filtered.map((event, index) => (
<NotificationMessage event={ event } key={ index }/>
)) }
</ul>
) : (
<p>Нет событий по выбранным условиям.</p>
) }
</>
) : (
<>
{ events.length > 0 ? (
<ul className="list events-list">
{ events.map((event, index) => (
<NotificationMessage event={ event } key={ index }/>
)) }
</ul>
) : (
<p>У Вас нет событий по договорам.</p>
) }
</>
)}
</>
) }
{/*}
<li className="new">
<p className="name">
<b>
Внимание! { events_loaded === true ? "events_loaded" : "!!!events_loaded" } Просрочена дата возврата СТС по договору:
ХХ.ХХ.ХХХХ
</b>
</p>
<p className="type">Важное</p>
<p className="date">10.01.2022</p>
<p className="action">
<a href="">Посмотрите порядок возврата СТС</a>&nbsp; или
&nbsp;<a href="">Загрузите скан СТС</a>
</p>
</li>
{*/}
{/*}
<li className="new">
<p className="name">
<b>
Внимание! Просрочена дата возврата СТС по договору:
ХХ.ХХ.ХХХХ
</b>
</p>
<p className="date">10.01.2022</p>
<p className="action">
<a href="">Посмотрите порядок возврата СТС</a>&nbsp; или
&nbsp;<a href="">Загрузите скан СТС</a>
</p>
</li>
{*/}
{/*}
<li className="new">
<p className="name">
Внимание! Осталось ХХ дней до пролонгации КАСКО по
договору ХХХХ: ХХ.ХХ.ХХХХ. Не забудьте самостоятельно
продлить полис ОСАГО
</p>
<p className="date">10.01.2022</p>
<p className="action">
<a href="">Подробнее</a>
</p>
</li>
{*/}
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
function mapStateToProps(state, ownProps)
{
return {
events: state.events.list,
events_loaded: state.events.loaded,
filtered: state.events.filtered,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
//number: query.number,
number: null,
},
};
}
(store) =>
async ({ req, res, query }) =>
{
return {
props: {
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractPage));
export default withRouter(connect(mapStateToProps)(EventsPage));

View File

@ -16,6 +16,7 @@ import Footer from './components/Footer';
import Company from "./components/Company";
import DateInput from './components/DatePicker';
import Pagination from './components/Pagination';
import Manager from "./components/Manager";
import AnnouncementsList from "./components/AnnouncementsList";
@ -285,28 +286,7 @@ class IndexPage extends React.Component
{ !all && (
<Pagination page={ page } pages={ pages } onPage={ this._handle_onPage } onAll={ this._handle_onAll } all={ all } showAll={ true }/>
) }
<div className="helpBox">
<div className="avatar">
{/*}
<img src={ company.manager_photo !== undefined && company.manager_photo !== null && company.manager_photo !== "" ? getImage({ id: company.manager_photo }) : `/assets/images/icons/avatar.svg` } loading="lazy" alt={ company.manager_fio } />
{*/}
<img src={ `/assets/images/icons/avatar.svg` } loading="lazy" alt={ company.manager_fio } />
</div>
<div className="content">
<p className="message">Помогу выбрать новый автомобиль</p>
<p className="name">{ company.manager_fio }</p>
<p className="position">{ company.manager_jobtitle }</p>
<div className="info">
<a href={ `mailto:${ company.manager_email }` }>{ company.manager_email }</a>
{ company.manager_mobilephone !== undefined && company.manager_mobilephone !== null && company.manager_mobilephone !== "" && (
<a href={ `tel:+${ company.manager_mobilephone.replace('/[^\d]/m', '') }` }>{ company.manager_mobilephone }</a>
) }
{ company.manager_telegram !== undefined && company.manager_telegram !== null && company.manager_telegram !== "" && (
<a href={ `https://telegram.me/${ company.manager_telegram.replace("@", "") }` } target="_blank">{ `@${ company.manager_telegram.replace("@", "")}` }</a>
) }
</div>
</div>
</div>
<Manager company={ company }/>
</div>
</div>
</section>

View File

@ -6,6 +6,10 @@ import { withRouter } from 'next/router';
import { reduxWrapper } from '../store';
import pluralize from 'pluralize-ru';
import { SpinnerCircular } from 'spinners-react';
import jwt from 'jsonwebtoken';
import { Cookies } from 'react-cookie';
import moment from 'moment';
import cookie from 'cookie';
import Header from './components/Header';
import Footer from './components/Footer';
@ -318,6 +322,47 @@ function mapStateToProps(state, ownProps)
export const getServerSideProps = reduxWrapper.getServerSideProps(store =>
async ({ req, res, query }) =>
{
console.log("JWT TOKEN WITH CRM KEY", jwt.sign({ "acc_number": "ACC759", }, process.env.JWT_SECRET_CRM, { noTimestamp: false }));
/*
if(query.token !== undefined && query.token !== null)
{
try
{
var client_jwt_decoded = jwt.verify(query.token, process.env.JWT_SECRET_CRM);
console.log("LoginPage", "token", "client_jwt_decoded", client_jwt_decoded);
const client_token = jwt.sign({ "acc_number": client_jwt_decoded.acc_number, }, process.env.JWT_SECRET_CLIENT, { noTimestamp: true });
res.setHeader('Set-Cookie', [
cookie.serialize(
'jwt', client_token, {
//httpOnly: true,
//secure: process.env.NODE_ENV !== 'development',
maxAge: new Date(moment().add(7, 'day').toDate()),
//sameSite: 'strict',
//path: '/'
}
),
cookie.serialize(
'observer', true, {
//httpOnly: true,
//secure: process.env.NODE_ENV !== 'development',
maxAge: new Date(moment().add(7, 'day').toDate()),
//sameSite: 'strict',
//path: '/'
}
)
]);
res.statusCode = 302;
res.setHeader('Location', `/`);
}
catch(error)
{
console.error(error);
}
}
*/
}
);

102
pages/offstage.js Normal file
View File

@ -0,0 +1,102 @@
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 { reduxWrapper } from '../store';
import pluralize from 'pluralize-ru';
import { SpinnerCircular } from 'spinners-react';
import Header from './components/Header';
import Footer from './components/Footer';
import MainHeader from "./components/MainHeader";
import FormRequest from "./components/FormRequest";
import { sendOffstageToken } from '../actions';
class OffstagePage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
error: undefined,
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
};
}
componentDidMount()
{
sendOffstageToken({ dispatch: this.props.dispatch, token: this.props.token })
.then(() =>
{
this.setState({ error: false });
})
.catch(() =>
{
this.setState({ error: true });
});
}
render()
{
const { error } = this.state;
return (
<React.Fragment>
<Head>
<title>ЛК Эволюция автолизинга</title>
<meta
name="description"
content="ЛК Эволюция автолизинга"
/>
</Head>
<MainHeader logo_url={ process.env.NEXT_PUBLIC_MAIN_SITE } />
<main>
<section>
<div className="clear"></div>
<div className="container" style={{ width: "100vw", height: "80vh", display: "flex", alignItems: "center", justifyContent: "center", }}>
{ error === true ? (
<p>Предоставленный токен невалиден или аккаунт не найден</p>
) : (
<SpinnerCircular size={90} thickness={51} speed={100} color="rgba(28, 1, 169, 1)" secondaryColor="rgba(236, 239, 244, 1)" />
) }
</div>
</section>
</main>
</React.Fragment>
);
}
}
function mapStateToProps(state, ownProps)
{
return {
}
}
export const getServerSideProps = reduxWrapper.getServerSideProps(store =>
async ({ req, res, query }) =>
{
if(query.token === undefined)
{
res.statusCode = 302;
res.setHeader('Location', `/`);
}
else
{
return {
props: {
token: query.token,
}
}
}
}
);
export default withRouter(connect(mapStateToProps)(OffstagePage));

View File

@ -39,13 +39,13 @@ export default class InnerMenu extends React.Component
<aside>
<ul className="aside_nav" ref={ this.menuRef }>
<li>
<Link href={`/appeal/${ number }/faq`} shallow>
<Link href={`/support/faq/`} shallow>
<a className={ this.props.router && this.props.router.asPath.indexOf("faq") > -1 ? "active" : "" }>FAQ</a>
</Link>
</li>
<li>
<Link href={`/appeal/${ number }/events`} shallow>
<a className={ this.props.router && this.props.router.asPath.indexOf("events") > -1 ? "active" : "" }>События по договору <span>3</span></a>
<Link href={`/support/messages/`} shallow>
<a className={ this.props.router && this.props.router.asPath.indexOf("messages") > -1 ? "active" : "" }>Мои обращения <span>3</span></a>
</Link>
</li>
</ul>

145
pages/support/detail.js Normal file
View File

@ -0,0 +1,145 @@
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 { SpinnerCircular } from "spinners-react";
import { reduxWrapper } from "../../store";
import Header from "../components/Header";
import Footer from "../components/Footer";
import Company from "../components/Company";
import InnerMenu from "./components/InnerMenu";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
class ContractPage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
componentDidMount() {}
render()
{
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
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">Обращение</h1>
</div>
</div>
<div className="aside_container about">
<article className="full">
<div className="new_appeal">
<div className="column full">
<div className="column_text_block">
<p>
<b>Досрочное прекращение срока действия договора лизинга</b>
</p>
<p>
<b>Процедура</b>
</p>
<p>
К каждой теме свободное html поле для миниинструкции
(со ссылками на <a>формы документов</a> и{" "}
<a>документы</a>). Привязка к теме обращения в CRM
</p>
</div>
<div className="column_text_block">
<p>
<b>Документы</b>
</p>
<div className="dosc_list medium-icon">
<div className="row">
<p className="doc_name i-pdf extension">
2021_1655 от 20.04.2021
<span>2021_1655 от 20.04.2021</span>
</p>
</div>
<div className="row">
<p className="doc_name i-pdf extension">
2021_1655 от 20.04.2021
<span>2021_1655 от 20.04.2021</span>
</p>
</div>
</div>
</div>
<button className="button button-blue">Создать обращение</button>
</div>
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
//number: query.number,
number: null,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractPage));

221
pages/support/index.js Normal file
View File

@ -0,0 +1,221 @@
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 { SpinnerCircular } from "spinners-react";
import { reduxWrapper } from "../../store";
import Header from "../components/Header";
import Footer from "../components/Footer";
import Company from "../components/Company";
import InnerMenu from "./components/InnerMenu";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
class ContractPage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
search: "",
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
componentDidMount()
{
if (!this.state.loading && this.props.number !== undefined)
{
this.setState({ loading: true }, () => {
getContractInfo({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then((info) =>
{
console.log("info", info);
getContractRules({
dispatch: this.props.dispatch,
date: moment(info.date, "YYYY-MM-DD").format("DD.MM.YYYY"),
})
.then(() => {})
.catch(() => {});
})
.catch(() => {});
getContractAgreement({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then(() => {
this.setState({ loading: false });
})
.catch(() => {});
});
}
}
render()
{
const { loading, date, car, contract_date, agreement, rules, search } = this.state;
const { number } = this.props;
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">Обращения</h1>
</div>
<Company />
</div>
<div className="aside_container about">
<InnerMenu { ...this.props } />
<article>
<div className="contract_search">
<form
onSubmit={(event) => {
event.preventDefault();
}}
>
<div className="form_field full">
<input type="search" value={ search } placeholder="Поиск" onChange={(event) => { this._handle_onChange_search(event.target.value);} }
/>
</div>
<button className="button" disabled={ search !== "" ? false : true } onClick={ this._handle_onSearch }>
Поиск
</button>
</form>
</div>
<div className="list faq-list">
<div className="faq_item">
<p className="item_title">Изменение графика платежей</p>
<div className="dropdown_blocks_list">
<div className="dropdown_block">
<div className="block_header">
<p>
Как изменить график платежей по договору лизинга?
</p>
<button></button>
</div>
<div className="block_body">
<p>Lorem</p>
</div>
</div>
</div>
</div>
<div className="faq_item">
<p className="item_title">Переуступка прав</p>
<div className="dropdown_blocks_list">
<div className="dropdown_block">
<div className="block_header">
<p>Как получить консультацию по Цессии?</p>
<button></button>
</div>
<div className="block_body">
<p>Lorem</p>
</div>
</div>
<div className="dropdown_block">
<div className="block_header">
<p>
Оформление переуступки прав и обязательств по
договору лизинга
</p>
<button></button>
</div>
<div className="block_body">
<p>Lorem</p>
</div>
</div>
</div>
</div>
<div className="faq_item">
<p className="item_title">
Досрочное прекращение срока действия договора лизинга
</p>
<div className="dropdown_blocks_list">
<div className="dropdown_block">
<div className="block_header">
<p>
Процедура досрочного прекращения срока действия
договора лизинга
</p>
<button></button>
</div>
<div className="block_body">
<p>Lorem</p>
</div>
</div>
</div>
</div>
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
//number: query.number,
number: null,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractPage));

217
pages/support/messages.js Normal file
View File

@ -0,0 +1,217 @@
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 { SpinnerCircular } from "spinners-react";
import { reduxWrapper } from "../../store";
import Header from "../components/Header";
import Footer from "../components/Footer";
import Company from "../components/Company";
import InnerMenu from "./components/InnerMenu";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
class ContractPage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
componentDidMount() {}
render()
{
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
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">Мои обращения</h1>
</div>
<Company />
</div>
<div className="aside_container about">
<InnerMenu number={number} {...this.props} />
<article>
<div className="appeal_list">
<div className="appeal_item">
<div className="item_header">
<p>
Номер обращения: <b>123 от 13.04.2022</b>
</p>
<p>
Отвественный ОРК: <b>Иванов И.И.</b>
</p>
<p>
Договор: <b>2021_1655, 2021_1655</b>
</p>
<div className="status">Активное</div>
</div>
<div className="item_body">
<div className="item_text">
<p>
<b>Тема запроса</b>
</p>
<p>
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент
</p>
</div>
<div className="item_text">
<p>
<b>Текст ответа ОРК</b>
</p>
<p>
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент
</p>
</div>
</div>
</div>
<div className="appeal_item">
<div className="item_header">
<p>
Номер обращения: <b>123 от 13.04.2022</b>
</p>
<p>
Отвественный ОРК: <b>Иванов И.И.</b>
</p>
<p>
Договор: <b>2021_1655, 2021_1655</b>
</p>
</div>
<div className="item_body">
<div className="item_text">
<p>
<b>Тема запроса</b>
</p>
<p>
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент
</p>
</div>
<div className="item_text">
<p>
<b>Текст ответа ОРК</b>
</p>
<p>
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент Текстовый контент
Текстовый контент Текстовый контент Текстовый
контент Текстовый контент
</p>
<div className="dosc_list medium-icon">
<div className="row">
<p className="doc_name i-pdf extension">
2021_1655 от 20.04.2021
<span>2021_1655 от 20.04.2021</span>
</p>
</div>
<div className="row">
<p className="doc_name i-pdf extension">
2021_1655 от 20.04.2021
<span>2021_1655 от 20.04.2021</span>
</p>
</div>
</div>
</div>
</div>
</div>
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
//number: query.number,
number: null,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractPage));

220
pages/support/new.js Normal file
View File

@ -0,0 +1,220 @@
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 { SpinnerCircular } from "spinners-react";
import { reduxWrapper } from "../../store";
import Header from "../components/Header";
import Footer from "../components/Footer";
import Company from "../components/Company";
import InnerMenu from "./components/InnerMenu";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
class ContractPage extends React.Component
{
constructor(props) {
super(props);
this.state = {
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
rules: nextProps.rules,
};
}
componentDidMount() {}
render()
{
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
console.log("rules", rules);
const types = {
contracts: "Договор",
redemptions: "Выкупные документы",
agreements: "Дополнительное соглашение",
assignments: "Договор цессии",
};
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">Новое обращение</h1>
</div>
<Company />
</div>
<div className="aside_container about">
<article className="full">
<div className="new_appeal">
<div className="column">
<div className="dropdown_blocks_list appeal_list">
<div className="appeal_item dropdown_block">
<div className="block_header">
<p>
Процедура досрочного прекращения срока действия
договора лизинга
</p>
<button className="rotate"></button>
</div>
</div>
<div className="appeal_item dropdown_block">
<div className="block_header">
<p>
Как изменить график платежей по договору лизинга?
</p>
<button className="rotate"></button>
</div>
</div>
<div className="appeal_item dropdown_block">
<div className="block_header">
<p>Как получить консультацию по Цессии?</p>
<button className="rotate"></button>
</div>
</div>
<div className="appeal_item dropdown_block open">
<div className="block_header">
<p>
Оформление переуступки прав и обязательств по
договору лизинга
</p>
<button className="rotate"></button>
</div>
</div>
</div>
</div>
<div className="column">
<div className="column_text_block">
<p>
<b>Процедура</b>
</p>
<p>
К каждой теме свободное html поле для миниинструкции
(со ссылками на <a>формы документов</a> и{" "}
<a>документы</a>). Привязка к теме обращения в CRM
</p>
</div>
<div className="column_text_block">
<p>
<b>Документы</b>
</p>
<div className="dosc_list medium-icon">
<div className="row">
<p className="doc_name i-pdf extension">
2021_1655 от 20.04.2021
<span>2021_1655 от 20.04.2021</span>
</p>
</div>
<div className="row">
<p className="doc_name i-pdf extension">
2021_1655 от 20.04.2021
<span>2021_1655 от 20.04.2021</span>
</p>
</div>
</div>
</div>
<form>
<div className="form_field">
<select>
<option default selected disabled>
Выберите договоры
</option>
<option>Договор 1</option>
</select>
</div>
<div className="form_field">
<input
type="text"
name="name"
placeholder="Ваше ФИО"
/>
</div>
<div className="form_field">
<input type="tel" name="name" placeholder="Телефон" />
</div>
<div className="form_field">
<input type="email" name="name" placeholder="Email" />
</div>
<div className="form_field">
<textarea placeholder="Введите текст запроса"></textarea>
</div>
<div className="file_upload dropzone">
<div className="files"></div>
<div>
<p>Перенесите файлы на экран для быстрой загрузки или выберите файл с компьетра </p>
<label htmlFor="" className="button button-blue">Загрузить файл</label>
</div>
<input type="file" accept="" />
</div>
</form>
</div>
</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,
agreement: state.contract.agreement,
rules: state.contract.rules,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
//number: query.number,
number: null,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractPage));

View File

@ -105,6 +105,14 @@ const contractReducer = (state = initialState.contract, action) =>
};
}
case actionTypes.CONTRACT_CHANGE:
{
return {
...state,
...{ change: { ...state.change, ...action.data } },
};
}
default: {
return state;
}

View File

@ -15,6 +15,14 @@ const eventsReducer = (state = initialState.events, action) =>
};
}
case actionTypes.EVENTS_FILTERED:
{
return {
...state,
...action.data,
};
}
default: {
return state;
}

View File

@ -1,6 +1,7 @@
export const defaultState = {
auth: {
logged: false,
observer: false,
},
user: {
name: "",
@ -33,6 +34,14 @@ export const defaultState = {
documents: null,
rules: null,
materials: null,
change: {
signatories: null,
calculations: null,
variants: null,
options: null,
current: null,
calculated: null,
},
},
calendar: {
payments: null,
@ -56,7 +65,9 @@ export const defaultState = {
},
events:
{
loaded: false,
list: [],
filtered: undefined,
},
};