Conflicts:
	css/main/style.css
	css/main/style.less
This commit is contained in:
merelendor 2022-08-10 11:40:13 +03:00
commit 9f95f2fff7
112 changed files with 18096 additions and 801 deletions

View File

@ -0,0 +1,33 @@
import axios from 'axios';
if(process.browser)
{
FormData.prototype.appendObject = function(obj, namespace)
{
let keyName;
for (var key in obj)
{
if (obj.hasOwnProperty(key))
{
keyName = [namespace, '[', key, ']'].join('');
this.append(keyName, obj[key]);
}
}
};
}
export const getAnnouncements = () =>
{
return new Promise((resolve, reject) =>
{
axios.get(`${ process.env.NEXT_PUBLIC_API_HOST }/api/announcements/`)
.then((response) =>
{
resolve(response.data.announcements);
})
.catch((error) =>
{
console.error(error);
});
});
}

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();
});
}

132
actions/eventsActions.js Normal file
View File

@ -0,0 +1,132 @@
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';
if(process.browser)
{
FormData.prototype.appendObject = function(obj, namespace)
{
let keyName;
for (var key in obj)
{
if (obj.hasOwnProperty(key))
{
keyName = [namespace, '[', key, ']'].join('');
this.append(keyName, obj[key]);
}
}
};
}
export const getEvents = ({ dispatch, type, contract }) =>
{
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`, {}, {
withCredentials: true,
})
.then((response) =>
{
console.log("getEvents", "response", response.data);
const events = response.data;
const filtered_events = [];
console.log("events");
console.log(events);
dispatch({ type: actionTypes.EVENTS, data: { list: events, loaded: true } });
resolve();
})
.catch((error) =>
{
console.log("error");
console.error(error);
reject();
});
});
}
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,6 +22,31 @@ if(process.browser)
};
}
export const getImage = ({ id }) =>
{
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();
});
});
}
export const getFile = ({ id, filename }) =>
{
console.log("getFile");

View File

@ -6,4 +6,7 @@ export * from './companyActions';
export * from './fileActions';
export * from './navigationActions';
export * from './formsActions';
export * from './settingsActions';
export * from './settingsActions';
export * from './announcementsActions';
export * from './eventsActions';
export * from './supportActions';

80
actions/supportActions.js Normal file
View File

@ -0,0 +1,80 @@
import axios from 'axios';
import * as actionTypes from '../constants/actionTypes';
import * as currentState from '../reducers/initialState';
if(process.browser)
{
FormData.prototype.appendObject = function(obj, namespace)
{
let keyName;
for (var key in obj)
{
if (obj.hasOwnProperty(key))
{
keyName = [namespace, '[', key, ']'].join('');
this.append(keyName, obj[key]);
}
}
};
}
export const getSupportThemes = ({ dispatch, query, }) =>
{
console.log("ACTION", "support", "getSupportThemes", { query });
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/support/themes`, {
query
},
{
withCredentials: true,
})
.then(async (response) =>
{
console.log("getContractRules", "response.data", response.data);
dispatch({ type: actionTypes.SUPPORT_THEMES, data: { themes: response.data.themes } });
resolve();
})
.catch((error) =>
{
console.error(error);
reject();
});
});
}
export const sendNewAppeal = ({ name, phone, email, company }) =>
{
return new Promise((resolve, reject) =>
{
var formData = new FormData();
formData.append("form", "FORM_LEASING_REQUESTS");
formData.append("FORM_FIELD_FIO", name);
formData.append("FORM_FIELD_PHONE", phone);
formData.append("FORM_FIELD_EMAIL", email);
formData.append("FORM_FIELD_COMPANY", company);
formData.append("FORM_FIELD_PAGE_NAME", document.title);
formData.append("FORM_FIELD_PAGE_URL", window.location.href);
axios.post(`${ process.env.NEXT_PUBLIC_API_HOST }/api/forms/`, formData)
.then((response) =>
{
if(response.data.status === "complete")
{
resolve();
}
else
{
reject();
}
})
.catch((error) =>
{
console.error(error);
reject();
});
});
}

View File

@ -13,4 +13,19 @@ 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 CALENDAR = 'CALENDAR';
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_FILTERED = 'EVENTS_FILTERED';
export const SUPPORT_THEMES = 'SUPPORT_THEMES';
export const SUPPORT_THEMES_SEARCHED = 'SUPPORT_THEMES_SEARCHED';
export const SUPPORT_APPEALS = 'SUPPORT_APPEALS';
export const SUPPORT_APPEAL = 'SUPPORT_APPEAL';

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
{"version":3,"sources":["style.less"],"names":[],"mappings":"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"}
{"version":3,"sources":["style.less"],"names":[],"mappings":"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"}

View File

@ -161,6 +161,9 @@ button,
}
// Labels
.form_field {
position: relative;
}
input[type="checkbox"] {
display: none;
visibility: hidden;
@ -195,8 +198,9 @@ 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);
}
}
}
@ -216,12 +220,21 @@ input[type="radio"] {
border: 1px solid rgba(0, 16, 61, 0.12);
box-sizing: border-box;
border-radius: 100%;
width: 16px;
min-width: 16px;
height: 16px;
position: absolute;
left: 0;
top: 2px;
}
}
&:checked + label {
&:before {
background: #fff;
box-shadow: inset 0px 0 0px 5px #005FF9;
border-color: #005FF9;
border: 0;
}
}
&:disabled + label {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -469,7 +469,7 @@
// Поиск договора в лк
.contract_search {
margin-bottom: 55px;
margin-bottom: 40px;
@media all and (max-width: 1600px) and (min-width: 1280px) {
margin-bottom: 30px;
@ -481,6 +481,15 @@
justify-content: space-between;
.form_field {
&.full {
width: 100% !important;
margin-right: 30px !important;
@media all and (max-width: 960px) {
margin-right: 0 !important;
}
}
&:first-child {
width: calc(50% - 15px);
min-width: calc(50% - 15px);
@ -501,6 +510,10 @@
.button {
width: 158px;
min-width: 158px;
@media all and (max-width: 768px) {
display: none;
}
}
input + label {
@ -510,7 +523,7 @@
}
@media all and (max-width: 960px) {
margin-bottom: 40px;
margin-bottom: 20px;
form {
flex-wrap: wrap;
justify-content: flex-start;
@ -595,6 +608,8 @@
background: var(--blue);
color: #fff;
display: none;
&:disabled {
opacity: 0.48;
}
@ -829,3 +844,410 @@
}
}
}
.settings_user_control {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 45px;
p {
font-weight: 700;
}
div {
display: flex;
align-items: center;
gap: 0 7px;
}
@media all and (max-width: 1279px) {
p {
width: 160px;
margin-right: 16px;
min-width: 160px;
}
div {
width: 100%;
button {
&:first-child {width: 60%};
&:last-child {width: 40%;}
}
}
}
@media all and (max-width: 768px) {
display: block;
margin-bottom: 35px;
width: 100%;
p {
width: 100%;
}
div {
display: block;
button {
width: 100% !important;
margin-top: 16px;
}
}
}
}
.settings_table {
display: table;
border-collapse: collapse;
width: 100%;
@media all and (max-width: 1279px) {
display: block;
}
.table_row {
display: table-row;
@media all and (max-width: 1279px) {
display: block;
padding-bottom: 16px;
margin-bottom: 16px;
border-bottom: 1px solid #EDEFF5;
padding-left: 55px;
background: url("../../public/assets/images/icons/user.svg") no-repeat top left;
position: relative;
}
@media all and (max-width: 768px) {
padding-left: 0;
background: transparent;
}
.table_cell {
display: table-cell;
padding: 18px 12px;
border: 1px solid #EDEFF5;
position: relative;
&.delete {
position: static;
}
@media all and (max-width: 1279px) {
display: flex;
flex-wrap: wrap;
border: 0;
font-size: 13px;
line-height: 20px;
padding: 0;
margin-bottom: 4px;
&:before {
content: attr(data-title);
color: #8E94A7;
font-weight: 700;
display: block;
width: 190px;
padding-right: 10px;
}
}
@media all and (max-width: 768px) {
&:before {
width: 100%;
margin-bottom: 2px;
}
}
&:last-child {
border-left: 0;
min-width: 36px;
button {
position: absolute;
width: 16px;
height: 16px;
padding: 0;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
visibility: hidden;
pointer-events: none;
background: url("../../public/assets/images/icons/icon-delete.svg") no-repeat center;
}
@media all and (max-width: 1279px) {
&:before {
display: none;
border: 0;
}
button {
bottom: auto;
left: auto;
width: 32px;
height: 32px;
background: url("../../public/assets/images/icons/Trash.svg") no-repeat center;
font-size: 0;
text-indent: -999px;
overflow: hidden;
}
}
@media all and (max-width: 768px) {
button {
background: transparent;
text-indent: 0;
font-weight: 600;
font-size: 15px;
line-height: 20px;
color: #A8026B;
width: 140px;
position: relative;
}
}
}
&:nth-last-child(2) {
border-right: 0;
}
input {
border: 0;
outline: none;
background: #fff;
font-size: 15px;
padding: 0;
&::placeholder {
color: var(--text_not_active);
font-size: 15px;
}
@media all and (max-width: 1279px) {
padding: 0 12px;
border: 1px solid rgba(0, 16, 61, 0.12);
height: 40px;
max-width: 320px;
width: 100%;
box-sizing: border-box;
}
@media all and (max-width: 768px) {
max-width: none;
width: 100%;
}
}
.settings_dropdown {
font-family: 'Montserrat',sans-serif;
font-weight: 400;
cursor: pointer;
width: 100%;
text-align: left;
font-weight: 400;
justify-content: flex-start;
font-size: 15px;
line-height: 20px;
color: #0C0C0C;
padding: 0;
background: url(/assets/images/icons/company-arrow.svg) no-repeat 100% 50%;
&[data-selected="false"] {
color: var(--text_not_active);
}
@media all and (max-width: 1279px) {
border: 1px solid rgba(0, 16, 61, 0.12);
padding: 0 10px;
background-position: calc(100% - 10px) 50%;
width: calc(100% - 200px);
max-width: 320px;
}
@media all and (max-width: 768px) {
max-width: none;
width: 100%;
}
}
.dropdown_list {
position: absolute;
top: 100%;
left: 0;
width: 412px;
display: none;
background: #FFFFFF;
box-shadow: 0px 4px 32px rgba(0, 0, 0, 0.16);
padding: 25px 35px;
z-index: 9;
@media all and (max-width: 1279px) {
left: 200px;
}
@media all and (max-width: 768px) {
left: 0;
right: 0;
width: 100%;
padding: 16px;
}
&.opened {
display: block;
}
.list_item {
position: relative;
padding-bottom: 16px;
margin-bottom: 16px;
border-bottom: 1px solid var(--inactive);
label {
font-weight: 700;
padding-left: 0;
padding-right: 30px;
line-height: 23px;
&:before {
right: 0;
left: auto;
}
span {
display: block;
font-weight: 400;
}
}
&:last-child {
border: 0;
padding-bottom: 0;
margin-bottom: 0;
}
}
}
}
&.table_header {
.table_cell {
color: #8E94A7;
font-weight: 700;
border: 0;
&:last-child {
border-left: 0 !important;
}
}
@media all and (max-width: 1279px) {
display: none;
}
}
}
&.editable {
.table_row {
&.editable {
.table_cell {
margin-bottom: 8px;
}
}
.table_cell {
&:last-child {
border: 1px solid #EDEFF5;
@media all and (max-width: 1279px) {
border: 0;
}
button {
pointer-events: all;
visibility: visible;
}
}
}
}
}
}
.new_appeal {
form {
.form_field {
margin-bottom: 14px;
}
textarea {
height: 208px;
}
}
}
.dropzone {
height: 208px;
position: relative;
border: 1px dashed #1C01A9;
border-radius: 4px;
background: rgba(28, 1, 169, 0.1);
text-align: center;
display: flex;
align-items: center;
justify-content: center;
margin-top: 30px;
.files {
width: 100%;
padding: 16px;
&:empty {
display: none;
}
}
[type="file"] {
cursor: pointer;
position: absolute;
opacity: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
div {
max-width: 404px;
text-align: center;
p {
color: #828282;
margin-bottom: 20px;
}
}
@media all and (max-width: 768px) {
border: 0;
background: transparent;
height: auto;
div {
p {
margin-bottom: 10px;
&:before {
content: attr(data-sm-text);
display: block;
}
span {
display: none;
}
}
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
{"version":3,"sources":["style.less"],"names":[],"mappings":"AAAA,OACE,eAAA,CACA,cAAA,CACA,UAAA,CACA,MAAA,CACA,OAAA,CAEA,YAAA,CACA,cAAA,CACA,gBAAA,CACA,mDAEA,gBAAmC,uBAAwB,kBAA3D,OACE,WAAA,CACA,cAAA,CACA,kBAfJ,MAkBE,YACE,cAAA,CACA,YAAA,CACA,kBAAA,CACA,6BAAA,CACA,SAAA,CACA,gBAEA,MARF,WAQG,OACC,aA3BN,MA+BE,GACE,oBAAA,CACA,WAEA,MAJF,EAIG,MACC,UAAW,gBApCjB,MAwCE,cACE,aAAA,CACA,cAAA,CACA,6BAAA,CACA,8BAAA,CACA,YAAA,CACA,kBAAA,CACA,6BAAA,CACA,WAAA,CACA,WAEA,MAXF,aAWG,YACC,cAAA,CACA,eAAA,CACA,eAtDN,MAwCE,aAiBE,IACE,aACE,aA3DR,MAwCE,aAiBE,IAKE,IACE,aAGE,MA1BR,aAiBE,IAKE,GAGE,GACG,IAAI,cACH,kBAGF,MA9BR,aAiBE,IAKE,GAGE,GAKG,YACC,kBAvEZ,MAwCE,aAiBE,IAKE,GAGE,GASE,EAAC,QACC,MAAO,WAAP,CACA,gBAGF,MAvCR,aAiBE,IAKE,GAGE,GAcG,OACC,GACE,MAAO,WAAP,CACA,gBAlFd,MA0FE,KACE,aAAA,CACA,oBAAA,CACA,cAAA,CACA,UAAA,CACA,WAAA,CACA,eAAgB,oDAGlB,gBAAmC,kBAI7B,MADJ,EACK,KACG,KACI,WAAA,CACA,WAAA,CACA,mBARd,MAaE,cACI,cAAA,CACA,cAKE,MAPN,aAIE,IAEE,GAAG,GACA,IAAI,cACH,kBAGF,MAXN,aAIE,IAEE,GAAG,GAKA,YACC,mBAOV,gBAAmC,kBAAnC,OACE,cAAA,CACA,gBAAA,CACA,YAGI,MADJ,EACK,KACG,KACI,WAAA,CACA,YATd,MAcE,cACI,qBAAA,CACA,qBAhBN,MAcE,aAME,KACE,WAAA,CACA,kBAtBN,MAcE,aAME,IAKE,aACE,aAAA,CACA,WAAA,CACA,SAAA,CACA,qBAAsB,uCAAtB,CACA,2BAAA,CACA,4BAAA,CACA,cAAA,CACA,MAAO,WAAP,CACA,eAAA,CAEA,cAAA,CACA,cAAA,CACA,eAAA,CACA,kBAAA,CACA,sBAAA,CACA,eAAA,CACA,gBA1CR,MAcE,aAME,IAyBI,IACE,aAAA,CACA,iBAAA,CACA,eAAA,CACA,iBAAA,CACA,QAAA,CACA,UAAA,CACA,YAEA,MAxCR,aAME,IAyBI,GASG,IAAI,QACH,aAIA,MA7CV,aAME,IAyBI,GAaE,GACG,IAAI,cACH,kBA5Dd,MAcE,aAME,IAyBI,GAaE,GAKE,GACE,eAhEd,MAcE,aAwDE,EAAC,eACE,UAAA,CACA,WAAA,CACA,eAAgB,8DAAhB,CACA,mBAAA,CACA,eAAA,CACA,kBAKP,gBAAkC,iBAAlC,OACE,YADF,MAGE,YACE,oBAJJ,MAOE,cACE,aAAA,CACA,cAAA,CACA,aAAA,CACA,YAXJ,MAOE,aAME,KACE,iBAAA,CACA,MAAA,CACA,WAhBN,MAOE,aAYE,EAAC,eACC,UAAA,CACA,WAAA,CACA,wBAtBN,MA0BE,KACE,UAAA,CACA,WAAA,CACA,cAAA,CACA"}
{"version":3,"sources":["style.less"],"names":[],"mappings":"AAAA,OACE,eAAA,CACA,cAAA,CACA,UAAA,CACA,MAAA,CACA,OAAA,CAEA,YAAA,CACA,cAAA,CACA,gBAAA,CACA,mDAEA,gBAAmC,uBAAwB,kBAA3D,OACE,WAAA,CACA,cAAA,CACA,kBAfJ,MAkBE,YACE,cAAA,CACA,YAAA,CACA,kBAAA,CACA,6BAAA,CACA,SAAA,CACA,gBAEA,MARF,WAQG,OACC,aA3BN,MA+BE,GACE,oBAAA,CACA,WAEA,MAJF,EAIG,MACC,UAAW,gBApCjB,MAwCE,cACE,aAAA,CACA,cAAA,CACA,6BAAA,CACA,8BAAA,CACA,YAAA,CACA,kBAAA,CACA,6BAAA,CACA,WAAA,CACA,WAEA,MAXF,aAWG,YACC,cAAA,CACA,eAAA,CACA,eAtDN,MAwCE,aAiBE,IACE,aACE,aA3DR,MAwCE,aAiBE,IAKE,IACE,aAGE,MA1BR,aAiBE,IAKE,GAGE,GACG,IAAI,cACH,kBAGF,MA9BR,aAiBE,IAKE,GAGE,GAKG,YACC,kBAvEZ,MAwCE,aAiBE,IAKE,GAGE,GASE,EAAC,QACC,MAAO,WAAP,CACA,gBAGF,MAvCR,aAiBE,IAKE,GAGE,GAcG,OACC,GACE,MAAO,WAAP,CACA,gBAlFd,MA0FE,aACE,YAAA,CACA,kBAAA,CACA,SA7FJ,MA0FE,YAKE,GAAK,GACH,aAAA,CACA,UAAA,CACA,WAAA,CACA,aAAA,CACA,iBAAA,CACA,kBAEA,MAbJ,YAKE,GAAK,EAQF,aAAa,QACZ,QAAS,iBAAT,CACA,aAAA,CACA,iBAAA,CACA,QAAA,CACA,UAAA,CACA,UAAA,CACA,WAAA,CACA,kBAAA,CACA,gBAAA,CACA,iBAAA,CACA,UAAA,CACA,kBAAA,CACA,eAEA,gBAAkC,iBAAlC,MA5BN,YAKE,GAAK,EAQF,aAAa,QAgBV,UAAA,CACA,WAAA,CACA,cAAA,CACA,gBAAA,CACA,KAAA,CACA,SAIJ,MAtCJ,YAKE,GAAK,EAiCF,iBAAiB,QAChB,aAIF,MA3CJ,YAKE,GAAK,EAsCF,oBACC,2EAGF,MA/CJ,YAKE,GAAK,EA0CF,qBACC,sEAGF,MAnDJ,YAKE,GAAK,EA8CF,sBACC,uEAIJ,gBAAkC,iBAAlC,MAxDF,aAyDI,SADF,MAxDF,YA2DG,GAAK,GACF,UAAA,CACA,WAAA,CACA,iCAxJR,MA0FE,YAkEE,IACE,kBA7JN,MA0FE,YAwEE,WACE,iBAAA,CACA,WAAA,CACA,QAAA,CACA,WAAA,CACA,aAEA,MA/EJ,YAwEE,UAOG,QACC,cAGF,gBAAmC,kBAAnC,MAnFJ,YAwEE,WAYI,aAGF,gBAAkC,iBAAlC,MAvFJ,YAwEE,WAgBI,6BAAA,CACA,cAAA,CACA,KAAA,CACA,MAAA,CACA,OAAA,CACA,QAAA,CACA,YAAA,CACA,iBAAA,CACA,YA1LR,MA0FE,YAwEE,UA4BE,QACE,kBAAA,CACA,sCAAA,CACA,wBAAA,CACA,kBAEA,MA1GN,YAwEE,UA4BE,OAMG,QACC,QAAS,EAAT,CACA,aAAA,CACA,OAAA,CACA,QAAA,CACA,kCAAA,CACA,mCAAA,CACA,6BAAA,CACA,iBAAA,CACA,SAAA,CACA,YAGF,gBAAkC,iBAAlC,MAvHN,YAwEE,UA4BE,QAqBI,yBADA,MAxHR,YAwEE,UA4BE,OAoBK,QAAS,cAlNpB,MA0FE,YAwEE,UA4BE,OAwBE,MACE,IACE,cAAA,CACA,gBAAA,CACA,+BAAA,CACA,aAAA,CACA,cAAA,CACA,YAAA,CACA,cAAA,CACA,6BAAA,CACA,kBAGE,MAzIZ,YAwEE,UA4BE,OAwBE,MACE,GAWG,IACE,OACC,QAAS,EAAT,CACA,aAAA,CACA,UAAA,CACA,WAAA,CACA,kBAAA,CACA,kBAAA,CACA,iBAAA,CACA,QAAA,CACA,QAEA,gBAAkC,iBAAlC,MApJd,YAwEE,UA4BE,OAwBE,MACE,GAWG,IACE,OAYG,UAAA,CACA,QAhPlB,MA0FE,YAwEE,UA4BE,OAwBE,MACE,GA8BE,GACE,iBAEA,MA9JZ,YAwEE,UA4BE,OAwBE,MACE,GA8BE,EAGG,IAAI,cACH,kBAGF,MAlKZ,YAwEE,UA4BE,OAwBE,MACE,GA8BE,EAOG,MACC,aAAA,CACA,MAAO,kBAAP,CACA,gBAEA,gBAAkC,iBAAlC,MAvKd,YAwEE,UA4BE,OAwBE,MACE,GA8BE,EAOG,MAMG,OAAA,CACA,YAPJ,MAlKZ,YAwEE,UA4BE,OAwBE,MACE,GA8BE,EAOG,KAYC,GACE,cAIJ,MAnLZ,YAwEE,UA4BE,OAwBE,MACE,GA8BE,EAwBG,MACC,eAAA,CACA,cAAA,CACA,gBAAA,CACA,aAAA,CACA,kBAEA,gBAAkC,iBAAlC,MA1Ld,YAwEE,UA4BE,OAwBE,MACE,GA8BE,EAwBG,MAQG,OAAA,CACA,UAAA,CACA,gBAAA,CACA,gBAIJ,MAlMZ,YAwEE,UA4BE,OAwBE,MACE,GA8BE,EAuCG,QACC,UAAA,CACA,gBAEA,gBAAkC,iBAAlC,MAtMd,YAwEE,UA4BE,OAwBE,MACE,GA8BE,EAuCG,QAKG,OAAA,CACA,mBAlSlB,MA0FE,YAwEE,UA4BE,OAwBE,MACE,GAgFE,GACE,MAAO,WAAP,CACA,gBAzSd,MA0FE,YAwEE,UA4BE,OAgHE,MACE,WAAY,WAAZ,CACA,gBAAA,CACA,iBAAA,CACA,aAAA,CACA,yBAAA,CACA,eAAA,CACA,cAAA,CACA,WAEA,gBAAkC,iBAAlC,MA9NR,YAwEE,UA4BE,OAgHE,MAWI,2BAzTZ,MA0FE,YAwEE,UA4BE,OA+HE,QACE,aAEA,gBAAkC,iBAAlC,MAtOR,YAwEE,UA4BE,OA+HE,QAII,sBAAA,CACA,eAAA,CACA,MAAO,WAAP,CACA,gBAAA,CACA,iBAAA,CACA,aAAA,CACA,eAAA,CACA,cAAA,CACA,MAAO,iBAAP,CACA,WA1UZ,MAiVE,KACE,aAAA,CACA,oBAAA,CACA,cAAA,CACA,UAAA,CACA,WAAA,CACA,eAAgB,oDAGlB,gBAAmC,kBAI/B,MADF,EACG,KACC,KACE,WAAA,CACA,WAAA,CACA,mBARR,MAaE,cACE,cAAA,CACA,cAKI,MAPN,aAIE,IAEE,GAAG,GACA,IAAI,cACH,kBAGF,MAXN,aAIE,IAEE,GAAG,GAKA,YACC,mBAOV,gBAAmC,kBAAnC,OACE,cAAA,CACA,gBAAA,CACA,YAIE,MADF,EACG,KACC,KACE,WAAA,CACA,YAVR,MAeE,cACE,qBAAA,CACA,oBAAA,CACA,eAlBJ,MAeE,aAME,KACE,WAAA,CACA,kBAvBN,MAeE,aAME,IAKE,aACE,aAAA,CACA,WAAA,CACA,SAAA,CACA,qBAAsB,uCAAtB,CACA,2BAAA,CACA,4BAAA,CACA,cAAA,CACA,MAAO,WAAP,CACA,eAAA,CAEA,cAAA,CACA,cAAA,CACA,eAAA,CACA,kBAAA,CACA,sBAAA,CACA,eAAA,CACA,gBA3CR,MAeE,aAME,IAyBE,IACE,aAAA,CACA,iBAAA,CACA,eAAA,CACA,iBAAA,CACA,QAAA,CACA,UAAA,CACA,YAEA,MAxCN,aAME,IAyBE,GASG,IAAI,QACH,aAIA,MA7CR,aAME,IAyBE,GAaE,GACG,IAAI,cACH,kBA7DZ,MAeE,aAME,IAyBE,GAaE,GAKE,GACE,eAjEZ,MAeE,aAwDE,EAAC,eACC,UAAA,CACA,WAAA,CACA,eAAgB,8DAAhB,CACA,mBAAA,CACA,eAAA,CACA,kBAKN,gBAAkC,iBAAlC,OACE,YADF,MAGE,YACE,oBAJJ,MAOE,cACE,aAAA,CACA,cAAA,CACA,aAAA,CACA,YAXJ,MAOE,aAME,KACE,iBAAA,CACA,MAAA,CACA,WAhBN,MAOE,aAYE,EAAC,eACC,UAAA,CACA,WAAA,CACA,wBAtBN,MA0BE,KACE,UAAA,CACA,WAAA,CACA,cAAA,CACA"}

View File

@ -22,7 +22,7 @@ header {
align-items: center;
justify-content: space-between;
padding: 0;
background: #fff;
background: #fff;
&:after {
display: none;
@ -88,6 +88,253 @@ header {
}
}
.system_nav {
display: flex;
align-items: center;
gap: 16px;
> li > a {
display: block;
width: 32px;
height: 32px;
font-size: 0px;
color: transparent;
position: relative;
&[data-notify]:before {
content: attr(data-notify);
display: block;
position: absolute;
top: -2px;
right: -2px;
width: 19px;
height: 19px;
border-radius: 100%;
line-height: 19px;
text-align: center;
color: #fff;
background: #A8026B;
font-size: 13px;
@media all and (max-width: 768px) {
width: 13px;
height: 13px;
font-size: 10px;
line-height: 14px;
top: 0;
right: 0;
}
}
&[data-notify="0"]:before {
display: none;
}
&[data-icon="phone"] {
background: url(/assets/images/icons/icon-phone-black.svg) no-repeat center;
}
&[data-icon="notify"] {
background: url(/assets/images/icons/icon-notify.svg) no-repeat center;
}
&[data-icon="message"] {
background: url(/assets/images/icons/icon-message.svg) no-repeat center;
}
}
@media all and (max-width: 768px) {
gap: 12px;
> li > a {
width: 21px;
height: 21px;
background-size: 21px !important;
}
}
li {
position: relative;
}
.backdrop {
position: absolute;
width: 657px;
top: 65px;
right: -96px;
display: none;
&.opened {
display: block;
}
@media all and (max-width: 1279px) {
width: 600px;
}
@media all and (max-width: 768px) {
background: rgba(12, 12, 12, 0.5);
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
padding: 55px 15px;
width: 100%;
}
.modal {
background: #FFFFFF;
box-shadow: 0px 4px 32px rgba(0, 0, 0, 0.16);
padding: 35px 20px 0 46px;
position: relative;
&:before {
content: "";
display: block;
width: 0;
height: 0;
border-left: 13px solid transparent;
border-right: 13px solid transparent;
border-bottom: 24px solid #fff;
position: absolute;
top: -24px;
right: 100px;
}
@media all and (max-width: 768px) {
&:before {display: none;}
padding: 17px 17px 0 17px;
}
.list {
li {
font-size: 13px;
line-height: 20px;
border-bottom: 1px solid #EDEFF5;
color: #2C2D2E;
padding: 10px 0;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
position: relative;
&.new {
&:after {
content: "";
display: block;
width: 13px;
height: 13px;
border-radius: 100%;
background: #2F80ED;
position: absolute;
top: 14px;
right: 0;
@media all and (max-width: 768px) {
right: auto;
left: 0;
}
}
}
p {
line-height: 20px;
&:not(:last-child) {
margin-bottom: 5px;
}
&.name {
color: #8E94A7;
width: calc(100% - 110px);
font-weight: 700;
@media all and (max-width: 768px) {
order: 2;
width: 100%;
}
b {
color: #2C2D2E;
}
}
&.date {
font-weight: 700;
font-size: 13px;
line-height: 20px;
color: #8E94A7;
margin-right: 30px;
@media all and (max-width: 768px) {
order: 1;
width: 100%;
margin-left: 20px;
margin-right: 0;
}
}
&.action {
width: 100%;
margin-top: 10px;
@media all and (max-width: 768px) {
order: 3;
text-align: center;
}
}
}
a {
color: var(--blue);
font-weight: 600;
}
}
}
.all {
background: var(--blue);
line-height: 40px;
text-align: center;
display: block;
margin: 15px -20px 0 -46px;
font-weight: 600;
font-size: 13px;
color: #fff;
@media all and (max-width: 768px) {
margin: 15px -17px 0 -17px;
}
}
.close {
display: none;
@media all and (max-width: 768px) {
margin: 0 -17px 0 -17px;
background: #fff;
color: var(--blue);
line-height: 40px;
text-align: center;
display: block;
font-weight: 600;
font-size: 13px;
width: calc(100% + 34px);
padding: 0;
}
}
}
}
}
.lk {
display: block;
text-decoration: none;
@ -98,24 +345,24 @@ header {
}
@media all and (max-width: 1420px) {
a {
&.logo {
img {
width: 180px;
height: 26px;
object-fit: contain;
}
&.logo {
img {
width: 180px;
height: 26px;
object-fit: contain;
}
}
}
.header_menu {
padding: 0 16px;
margin: 0 16px;
padding: 0 16px;
margin: 0 16px;
nav {
ul li {
&:not(:last-child) {
margin-right: 15px;
@ -133,26 +380,27 @@ header {
font-size: 15px;
line-height: 24px;
height: 86px;
a {
&.logo {
img {
width: 130px;
height: 20px;
}
}
&.logo {
img {
width: 130px;
height: 20px;
}
}
}
.header_menu {
padding: 0 16px 0 32px;
margin: 0 16px 0 32px;
padding: 0 16px 0 32px;
margin: 0 16px 0 32px;
border-right: 0;
nav {
height: 23px;
position: relative;
.nav_toggle {
display: block;
@ -174,39 +422,39 @@ header {
overflow: hidden;
}
ul {
display: block;
position: absolute;
background: #fff;
padding: 15px 20px;
top: 25px;
left: -20px;
width: 320px;
ul {
display: block;
position: absolute;
background: #fff;
padding: 15px 20px;
top: 25px;
left: -20px;
width: 320px;
&:not(.open) {
display: none;
&:not(.open) {
display: none;
}
li {
&:not(:last-child) {
margin-bottom: 6px;
}
li {
&:not(:last-child) {
margin-bottom: 6px;
}
a {
font-size: 15px;
}
a {
font-size: 15px;
}
}
}
}
a[href^="tel:"] {
width: 32px;
height: 32px;
background: url("/assets/images/icons/icon-header-phone.svg") no-repeat center;
text-indent: -9999px;
overflow: hidden;
margin-left: auto;
}
width: 32px;
height: 32px;
background: url("/assets/images/icons/icon-header-phone.svg") no-repeat center;
text-indent: -9999px;
overflow: hidden;
margin-left: auto;
}
}
}
@ -243,4 +491,4 @@ header {
background-size: contain;
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
{"version":3,"sources":["var.less"],"names":[],"mappings":"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"}
{"version":3,"sources":["var.less"],"names":[],"mappings":"AAAA,MACE,cAAA,CACA,wBAAA,CACA,cAAA,CACA,+BAAA,CACA,iBAAA,CACA,kCAAA,CACA,aAAA,CACA,kBAAA,CACA,eAAA,CACA,0BAgBF,KACE,cAAA,CACA,gBAAA,CACA,aAAA,CACA,YAAa,uBAAb,CACA,gBAEA,gBAAmC,uBAAwB,kBAA3D,KACE,cAAA,CACA,kBAGF,gBAAkC,iBAAlC,KACE,cAAA,CACA,kBAIJ,UACE,gBAGF,WACE,gBAAA,CACA,gBAAA,CACA,UAAA,CACA,gBAAA,CACA,WAAA,CACA,kBAEA,UAAC,OACC,QAAS,EAAT,CACA,aAAA,CACA,iBAAA,CACA,KAAA,CACA,MAAA,CACA,UAAA,CACA,QAAA,CACA,WAYF,gBAAmC,uBAAwB,kBAA3D,WACE,gBAAA,CACA,kBAGF,gBAAmC,kBAAnC,WACE,kBAGF,gBAAkC,iBAAlC,WACE,gBAAA,CACA,kBAGF,gBAAmC,kBAAnC,WACE,MAAO,kBAAP,CACA,eAGF,gBAAkC,iBAAlC,WACE,aAAA,CACA,MAAO,mBAIX,iBACE,YAAA,CACA,6BAAA,CACA,kBAEA,gBAAmC,kBACjC,gBAAC,QACC,QAAS,EAAT,CACA,aAAA,CACA,iBAAA,CACA,SAAA,CACA,UAAA,CACA,MAAA,CACA,QAAA,CACA,UAAA,CACA,WAAY,iBAflB,gBAmBE,OACE,YAEA,gBAAkC,iBAAlC,gBAHF,OAII,YAvBN,gBA2BE,SACE,MAAO,mBAEP,gBAHF,QAGG,YACC,WA/BN,gBA2BE,QAOE,cACE,iBAAA,CACA,YAAA,CACA,cAAA,CACA,6BAAA,CACA,gCAvCN,gBA2BE,QAOE,aAOE,KACE,MAAO,iBAGT,gBAAkC,iBAAlC,gBAlBJ,QAOE,cAYI,UADF,gBAlBJ,QAOE,aAcI,KACE,YAKN,gBAAkC,iBAAlC,gBA3BF,SA4BI,WADF,gBA3BF,QA8BI,cACE,gBAKN,gBAAC,MACC,OACE,WAAA,CACA,uBAAwB,eAAxB,CACA,oBAEA,gBAAmC,uBAAwB,kBAA3D,gBANH,MACC,OAMI,WAAA,CACA,qBAGF,gBAAmC,kBAAnC,gBAXH,MACC,OAWI,cAAA,CACA,qBAbN,gBAAC,MAiBC,SACE,MAAO,kBAAP,CACA,oBAEA,gBArBH,MAiBC,QAIG,MACC,WAGF,gBAAmC,uBAAwB,kBAA3D,gBAzBH,MAiBC,SASI,MAAO,kBAAP,CACA,qBAGF,gBAAkC,iBAAlC,gBA9BH,MAiBC,SAcI,qBAIJ,gBAAmC,kBAAnC,gBAnCD,OAoCG,cADF,gBAnCD,MAsCG,OAHF,gBAnCD,MAsCU,SACL,WAJJ,gBAnCD,MA0CG,MAAK,MACH,YAAA,CACA,kBAAA,CACA,gBAQR,eACE,cAAA,CACA,gBAAA,CACA,eAAA,CACA,aAAA,CACA,mBAEA,cAAC,WACC,gBAGF,gBAAmC,uBAAwB,kBAA3D,eACE,cAAA,CACA,kBAGF,gBAAmC,kBAAnC,eACE,cAAA,CACA,kBAGF,gBAAkC,iBAAlC,eACE,cAAA,CACA,kBAGF,gBAAkC,iBAAlC,eACE,oBAIJ,GACE,cAAA,CACA,iBAGF,GACE,cAAA,CACA,gBAAA,CACA,gBAAA,CACA,mBAEA,gBAAmC,uBAAwB,kBAA3D,GACE,cAAA,CACA,kBAGF,EAAC,OACC,cAAA,CACA,gBAAA,CACA,MAAO,sBAAP,CACA,YAAA,CACA,gBAEA,gBAAkC,iBAAlC,EAPD,OAQG,cAAA,CACA,kBAIJ,EAAC,aACC,aAIJ,GACE,cAAA,CACA,gBAAA,CACA,gBAAA,CACA,mBAEA,EAAC,aACC,aAIJ,GACE,cAAA,CACA,gBAAA,CACA,gBAAA,CACA,mBAEA,EAAC,aACC,aAIJ,WACE,cAAA,CACA,iBAEA,UAAC,YACC,cAGF,gBAAkC,iBAAlC,WACE,cAAA,CACA,kBAIJ,EACA,OACE,gBAIA,CAAC,SACC,MAAO,YAIX,EACE,oBAAA,CACA,MAAO,YAGT,IACE,sBAGF,OACE,aAAA,CACA,WAGF,gBAAkC,iBAChC,GACE,cAAA,CACA,iBAGF,GACE,cAAA,CACA,kBAIJ,SACE,iBAAA,CACA,eAAgB,2DAElB,mBACE,iBAAA,CACA,eAAgB,iEAElB,WACE,iBAAA,CACA,eAAgB,yDAElB,YACE,iBAAA,CACA,eAAgB,0DAGlB,OACE,iBAAA,CACA,eAAgB,2DAEhB,MAAC,cACC,eAAgB,2DAAhB,CACA,kBAEA,MAJD,aAIE,QACC,QAAS,iBAAT,CACA,UAAA,CACA,eAAA,CACA,iBAAA,CACA,QAAA,CACA,SAAA,CACA,UAAA,CACA,KAAA,CACA,aAAA,CACA,UAAA,CACA,YAAA,CACA,oBAAA,CACA,sBAAA,CACA,kBAAA,CACA,yBAGF,gBAAmC,uBAAwB,kBAA3D,MAtBD,cAuBG,iBAAA,CACA,qBAEA,MA1BH,aA0BI,QACC,UAAA,CACA,eAIJ,gBAAkC,iBAAlC,MAhCD,cAiCG,iBAAA,CACA,oBAAA,CACA,0BAEA,MArCH,aAqCI,QACC,aAAA,CACA,UAAA,CACA,WAAA,CACA,MAAA,CACA,SAKN,gBAAmC,uBAAwB,kBAA3D,OACE,iBAAA,CACA,sBAGF,gBAAkC,iBAAlC,OACE,iBAAA,CACA,oBAAA,CACA,2BAMH,UAAC,cAEA,eAAgB,2DAAhB,CACA,kBAEA,UALA,aAKC,QACA,QAAS,iBAAT,CACA,UAAA,CACA,eAAA,CACA,iBAAA,CACA,SAAA,CACA,SAAA,CACA,UAAA,CACA,KAAA,CACA,cAAA,CACA,UAAA,CACA,YAAA,CACA,oBAAA,CACA,sBAAA,CACA,kBAAA,CACA,yBAGD,gBAAmC,uBAAwB,kBAA3D,UAvBA,cAwBC,iBAAA,CACA,qBAEA,UA3BD,aA2BE,QACA,UAAA,CACA,aAAA,CACA,UAIF,gBAAkC,iBAAlC,UAlCA,cAmCC,iBAAA,CACA,oBAAA,CACA,0BAEA,UAvCD,aAuCE,QACD,aAAA,CACA,UAAA,CACA,WAAA,CACA,MAAA,CACA,SAMH,OACE,iBAAA,CACA,eAAgB,0DAAhB,CACA,qBAEA,gBAAmC,uBAAwB,kBAA3D,OACE,iBAAA,CACA,sBAGF,gBAAkC,iBAAlC,OACE,iBAAA,CACA,oBAAA,CACA,2BAIJ,SACE,MAAO,aAGT,QACE,MAAO,WAGT,gBAAkC,iBAChC,oBACE,cAIJ,OACC,YAAA,CACA,0BAAA,CACC,mBAHF,MAKC,GACC,eAAA,CACE,cAAA,CACA,gBAAA,CACA,UAAA,CACF,mBAEA,gBAAmC,kBAAnC,MAPD,GAQE,cAAA,CACA,qBAID,gBAAmC,kBAAnC,OACE,mBADF,MAGE,GACE,cAAA,CACA,kBAKN,sBACC,gBAAA,CACA,0BAEA,gBAAkC,iBAAlC,sBACC,yBAAA,CACA,kBAGD,QAA2B,uBAAwB,kBAAnD,sBACC,yBAAA,CACA"}

View File

@ -42,9 +42,13 @@ body {
}
}
.overflow {
overflow: hidden;
}
.container {
padding-top: 80px;
padding-bottom: 80px;
padding-bottom: 0;
width: 100%;
max-width: 1310px;
margin: auto;
@ -72,12 +76,16 @@ body {
@media all and (max-width: 1600px) and (min-width: 1280px) {
padding-top: 40px;
padding-bottom: 40px;
padding-bottom: 0;
}
@media all and (max-width: 1279px) {
padding-top: 30px;
}
@media all and (max-width: 960px) {
padding-top: 40px;
padding-bottom: 40px;
padding-top: 30px;
padding-bottom: 0;
}
@media all and (max-width: 1420px) {
@ -94,6 +102,21 @@ body {
.aside_container {
display: flex;
justify-content: space-between;
position: relative;
@media all and (min-width: 1280px) {
&:before {
content: "";
display: block;
position: absolute;
width: 1px;
top: -135px;
left: 0;
bottom: 0;
z-index: -1;
background: var(--inactive)
}
}
aside {
width: 415px;
@ -141,18 +164,36 @@ body {
&.about {
aside {
width: 305px;
width: 255px;
border-right: 1px solid var(--inactive);
padding-bottom: 80px;
@media all and (max-width: 1600px) and (min-width: 1280px) {
width: 265px;
width: 255px;
padding-bottom: 40px;
}
@media all and (max-width: 1279px) {
border-right: 0;
padding-bottom: 20px;
}
}
article {
width: calc(100% - 335px);
width: calc(100% - 285px);
padding-bottom: 80px;
&.full {
width: 100%;
}
@media all and (max-width: 1600px) and (min-width: 1280px) {
width: calc(100% - 295px);
padding-bottom: 40px;
}
@media all and (max-width: 960px) {
padding-bottom: 30px;
}
}
@ -162,7 +203,15 @@ body {
aside, article {
width: 100%;
}
aside.flex {
display: flex;
align-items: center;
flex-wrap: wrap;
}
}
}
}
@ -469,11 +518,14 @@ div {
.avans {
display: flex;
justify-content: flex-end;
justify-content: flex-start;
margin-bottom: 80px;
p {
font-size: 17px;
font-weight: 600;
font-weight: 700;
font-size: 15px;
line-height: 23px;
color: #000;
padding-bottom: 0px;
@media all and (max-width: 1280px) {
@ -481,6 +533,15 @@ div {
padding-bottom: 10px;
}
}
@media all and (max-width: 1279px) {
margin-bottom: 30px;
p {
font-size: 13px;
line-height: 20px;
}
}
}
.rw-calendar-btn-view {
@ -496,4 +557,15 @@ div {
font-size: 12px !important;
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",

4488
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -33,6 +33,7 @@
"react-dom": "17.0.2",
"react-google-recaptcha-v3": "^1.10.0",
"react-redux": "^7.2.6",
"react-slick": "^0.29.0",
"react-widgets": "^5.5.1",
"redux": "^4.1.2",
"redux-persist": "^6.0.0",

57
pages/500.js Normal file
View File

@ -0,0 +1,57 @@
import React from "react";
import Head from "next/head";
import Header from "./components/Header";
import Footer from "./components/Footer";
import Company from "./components/Company";
class Offline extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
static getDerivedStateFromProps(nextProps, prevState) {
return {};
}
componentDidMount() {}
render() {
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">
<h1 className="section_title">Личный кабинет</h1>
</div>
<div className="right">
<Company />
</div>
</div>
<div className="offline">
<p>
В настоящий момент ведутся технические работы. Если Вам
необходимо получить информацию, пожалуйста, свяжитесь с нами
по телефону: 8 800 111 22 33
</p>
</div>
</div>
</section>
</main>
<Footer />
</React.Fragment>
);
}
}
export default Offline;

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 }`,

60
pages/api/events.js Normal file
View File

@ -0,0 +1,60 @@
// 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);
console.log("API", "events", req.headers);
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 });
console.log("client_jwt_decoded");
console.log(client_jwt_decoded);
try
{
await axios.get(`${ process.env.CRM_API_HOST }/lk/Account/GetEvents/`, {
params: client_jwt_decoded,
headers: {
"Authorization": `Bearer ${ crm_jwt }`,
}
})
.then((crm_response) =>
{
res.status(200).json(crm_response.data);
})
.catch((error) =>
{
console.error(error);
res.status(500).send();
});
}
catch(e)
{
console.error(e);
res.status(500).send();
}
}
else
{
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

71
pages/api/file/image.js Normal file
View File

@ -0,0 +1,71 @@
// 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\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 });
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) =>
{
try
{
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(e);
res.status(500);
}
})
.catch((error) =>
{
console.error(error);
res.status(500);
});
}
else
{
res.status(403);
}
}
else
{
console.log("WTF?!?!?!!?");
}
}

View File

@ -0,0 +1,53 @@
// 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);
if(req.headers.cookie !== undefined)
{
const cookies = cookie.parse(req.headers?.cookie ? req.headers?.cookie : "");
if(cookies.jwt !== undefined && cookies.jwt !== null)
{
if(jwt.verify(cookies.jwt, process.env.JWT_SECRET_CLIENT))
{
const response = await new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_API_HOST }/api/account/support/themes/`, {
query: req.body.query,
})
.then((api_response) =>
{
console.log("RESPONSE");
console.log(api_response.data);
resolve(api_response.data);
})
.catch((error) =>
{
console.log("error");
console.error(error);
reject([]);
});
});
res.status(200).json(response);
}
else
{
res.status(403);
}
}
else
{
res.status(403);
}
}
}

View File

@ -0,0 +1,115 @@
import React from "react";
import { connect } from "react-redux";
import Slider from "react-slick";
import { getAnnouncements } from "../../../actions";
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>
);
}
class AnnouncementsList extends React.Component
{
constructor(props)
{
super(props);
this.state = {
company: {},
announcements: [],
};
}
componentDidMount()
{
getAnnouncements().then((announcements) => this.setState({ announcements: announcements })).catch(() => {});
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {};
}
render()
{
const settings = {
dots: false,
infinite: false,
speed: 500,
slidesToShow: 2,
slidesToScroll: 1,
centerMode: false,
variableWidth: false,
nextArrow: <NextArrow />,
prevArrow: <PrevArrow />,
};
const { announcements } = this.state;
return (
<div className="feed">
<div className="feed_list">
<Slider { ...settings }>
{ announcements.map(( announcement, index ) => (
<div className="feed_item" key={ index }>
<p className="item_title">{ announcement.title }</p>
<p className="item_desc" dangerouslySetInnerHTML={{ __html: announcement.content }}></p>
{ announcement.url !== null && (
<a href={ announcement.url } className="item_link">Подробнее</a>
) }
</div>
)) }
</Slider>
</div>
</div>
);
}
}
function mapStateToProps(state, ownProps)
{
return {};
}
export default connect(mapStateToProps)(AnnouncementsList);

View File

@ -8,6 +8,7 @@ class Company extends React.Component
super(props);
this.state = {
company: {},
opened: false,
}
}
@ -18,16 +19,48 @@ class Company extends React.Component
};
}
_handleOnClick = () =>
{
const { opened } = this.state;
//this.setState({ opened: !opened ? true : false })
}
render()
{
const { company } = this.state;
const { company, opened } = this.state;
console.log(this.props);
return (
<div className="right">
<p align="right">
<b>{ company.title }</b><br/>
{company.inn != null && <span>ИНН: { company.inn } </span>}
{company.kpp != null && <span>КПП: { company.kpp }</span>}
<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>
<div className={`companies_list ${ opened && "opened" }`}> {/* opened */}
<div className="company_item">
<p align="right">
<b>ООО ЮКС</b><br/>
ИНН: <span>12345678765</span> КПП: <span>13432-02</span>
</p>
</div>
<div className="company_item">
<p align="right">
<b>ООО Еще одно название</b><br/>
ИНН: <span>12345678765</span> КПП: <span>13432-02</span>
</p>
</div>
<div className="company_item selected">
<p align="right">
<b>ООО Друзья и КО</b><br/>
ИНН: <span>12345678765</span> КПП: <span>13432-02</span>
</p>
</div>
</div>
</div>
)
}

View File

@ -0,0 +1,77 @@
import React from "react";
import Link from "next/link";
export default class InnerMenu extends React.Component
{
constructor(props)
{
super(props);
this.state = {
type: undefined
};
this.menuRef = React.createRef();
}
componentDidMount()
{
const hash = this.props.router.asPath.split('#')[1];
this.setState({ type: hash });
}
componentDidUpdate(prevProps, prevState)
{
const hash = this.props.router.asPath.split('#')[1];
if(this.state.type !== hash)
{
this.setState({ type: hash });
}
}
render()
{
console.log("Events", "InnerMenu", "this.props.router", this.props.router);
const { type } = this.state;
return (
<aside>
<ul className="aside_nav">
<li>
<Link href={`/events`} shallow>
<a className={ type === undefined ? "active" : "" }>Все события</a>
</Link>
</li>
<li>
<Link href={`/events#restrictions`} shallow>
<a className={ type === "restrictions" ? "active" : "" }>Ограничения</a>
</Link>
</li>
<li>
<Link href={`/events#payments`} shallow>
<a className={ type === "payments" ? "active" : "" }>Платежи</a>
</Link>
</li>
<li>
<Link href={`/events#additional`} shallow>
<a className={ type === "additional" ? "active" : "" }>Дополнительные услуги</a>
</Link>
</li>
<li>
<Link href={`/events#fines`} shallow>
<a className={ type === "fines" ? "active" : "" }>Штрафы</a>
</Link>
</li>
<li>
<Link href={`/events#finance`} shallow>
<a className={ type === "finance" ? "active" : "" }>Банки</a>
</Link>
</li>
<li>
<Link href={`/events#pts`} shallow>
<a className={ type === "pts" ? "active" : "" }>ПТС</a>
</Link>
</li>
</ul>
</aside>
)
}
}

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

@ -0,0 +1,151 @@
import React from "react";
import { connect } from "react-redux";
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>
);
}
class FeedUsers extends React.Component
{
constructor(props)
{
super(props);
this.state = {
company: {},
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {};
}
render()
{
const settings = {
dots: false,
infinite: false,
speed: 500,
slidesToShow: 2,
slidesToScroll: 1,
centerMode: false,
variableWidth: false,
nextArrow: <NextArrow />,
prevArrow: <PrevArrow />,
};
return (
<div className="feed">
<div className="feed_list">
<Slider { ...settings }>
<div className="feed_item user">
<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">
<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">
<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">
<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">
<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">
<img src="/assets/images/icons/avatar.svg" alt="" />
<div>
<p className="item_title">Иванов Иван</p>
<p className="item_desc">
Менеджер по продажам
</p>
</div>
</div>
</Slider>
</div>
</div>
);
}
}
function mapStateToProps(state, ownProps)
{
return {};
}
export default connect(mapStateToProps)(FeedUsers);

View File

@ -0,0 +1,31 @@
import React from "react";
import Link from "next/link";
import NotificationMessage from "../../Events/NotificationMessage";
export default class NotificationsList extends React.Component
{
constructor(props)
{
super(props);
this.state = {
};
}
render()
{
const { events } = this.props;
console.log("events", events);
return (
<>
<ul className="list">
{ 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

@ -1,84 +1,261 @@
import React from "react";
import Link from "next/link";
import { connect } from "react-redux";
import { logout } from '../../../actions';
import { logout, getEvents } from "../../../actions";
import NotificationsList from "./NotificationsList";
export default class Header extends React.Component
class Header extends React.Component
{
constructor(props)
constructor(props)
{
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 "Договоры";
if (route.indexOf("/documents/") > -1) return "Взаиморасчеты и закрывающие документы";
if (route.indexOf("/settings/") > -1) return "Настройки";
if (route.indexOf("/contract") === 0) return "Договоры";
return null;
};
_handle_onToggleMenu = () =>
{
this.setState({
menuOpened: !this.state.menuOpened
menuOpened: !this.state.menuOpened,
});
};
_getActiveLink = (route) =>
{
if(route === "/") return "Договоры";
if(route.indexOf("/documents/") > -1) return "Взаиморасчеты и закрывающие документы";
if(route.indexOf("/settings/") > -1) return "Настройки";
if(route.indexOf("/contract") === 0) return "Договоры";
return null;
}
_handle_onLogout = () =>
{
logout({ dispatch: this.props.dispatch });
};
_handle_onToggleNotifications = () =>
{
const { notificationsOpened } = this.state;
this.setState({ notificationsOpened: notificationsOpened ? false : true });
}
render()
_handle_onToggleMessages = () =>
{
const { menuOpened } = this.state;
const { messagesOpened } = this.state;
this.setState({ messagesOpened: messagesOpened ? false : true });
}
_renderEvent = (event, index) =>
{
switch(event.event_type)
{
case "kasko_prolong":
{
return (
<li className="new" key={ index }>
<p className="name"><b>Тут бы какое-то сообщение передавать а не просто параметры, непонятно СКОЛЬКО дней осталось ДО окончания КАСКО. Или параметр kasko_end. Договор: { event.contract_number }, полис: { event.add_info }</b></p>
<p className="date">{ event.event_date }</p>
<p className="action">
<Link href={`/${ event.contract_number }`}>
<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 { 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">
<a href="/" className="logo">
<img src="/assets/images/logo.svg" alt="" width="217px" height="32px" />
</a>
<Link href={`/`} shallow>
<a className="logo">
<img
src="/assets/images/logo.svg"
alt=""
width="217px"
height="32px"
/>
</a>
</Link>
<div className="header_menu">
<nav>
<button className="nav_toggle" onClick={ this._handle_onToggleMenu }>
{ this.props.router && this._getActiveLink(this.props.router.route) }
<button
className="nav_toggle"
onClick={this._handle_onToggleMenu}
>
{this.props.router && this._getActiveLink(this.props.router.route)}
</button>
<ul id="menu_list" className={ menuOpened ? "open" : "" }>
<ul id="menu_list" className={menuOpened ? "open" : ""}>
<li>
<Link href={`/`} shallow>
<a className={ this.props.router && (this.props.router.route === "/" || this.props.router.route.indexOf("/contract") === 0) ? "active" : "" }>Договоры</a>
<a className={ this.props.router && (this.props.router.route === "/" || this.props.router.route.indexOf("/contract") === 0) ? "active" : "" }>
Договоры
</a>
</Link>
</li>
<li>
<Link href={`/documents/calendar/`} shallow>
<a className={ this.props.router && this.props.router.route.indexOf("/documents/") === 0 ? "active" : "" }>Взаиморасчеты и закрывающие документы</a>
<a className={ this.props.router && this.props.router.route.indexOf("/documents") === 0 ? "active" : "" }>
Взаиморасчеты и закрывающие документы
</a>
</Link>
</li>
<li>
<Link href="/settings/phone/" shallow>
<a className={ this.props.router && this.props.router.route.indexOf("/settings/") === 0 ? "active" : "" }>Настройки</a>
<a className={ this.props.router && this.props.router.route.indexOf("/settings") === 0 ? "active" : "" }>
Настройки
</a>
</Link>
</li>
{/*}
<li>
<Link href={ process.env.NEXT_PUBLIC_MAIN_SITE }>
<a>Основной сайт</a>
<Link href="/support/faq/" shallow>
<a className={ this.props.router && this.props.router.route.indexOf("/support") === 0 ? "active" : "" }>Обращения</a>
</Link>
</li>
{*/}
{/*
<li>
<Link href={ process.env.NEXT_PUBLIC_MAIN_SITE }>
<a>Основной сайт</a>
</Link>
</li>
*/}
</ul>
</nav>
<a href="tel:88003337575">8 800 333 75 75</a>
</div>
<button className="lk" title="Выход" onClick={ () => this._handle_onLogout() }></button>
<ul className="system_nav">
<li>
<a data-icon="phone" className="button">Телефон</a>
</li>
<li>
<a data-icon="notify" data-notify={ events.length } className="button" onClick={ this._handle_onToggleNotifications }>
Уведомления
</a>
<div className={`backdrop ${ notificationsOpened && "opened" }`}>
<div className="modal">
{ events_loaded && (
<>
{ events.length > 0 ? (
<NotificationsList events={ events }/>
) : (
<p style={{ paddingBottom: "30px" }}>Нет действующих событий для показа</p>
) }
</>
)}
<button className="close" onClick={ this._handle_onToggleNotifications }>Закрыть</button>
</div>
</div>
</li>
{/*}
<li>
<Link href="/support/" shallow>
<a data-icon="message" data-notify="0" className="button" onClick={ this._handle_onToggleMessages }>
Сообщения
</a>
</Link>
</li>
{*/}
<li>
<button
className="lk"
title="Выход"
onClick={() => this._handle_onLogout()}
></button>
</li>
</ul>
</div>
</header>
)
);
}
}
function mapStateToProps(state, ownProps)
{
return {
observer: state.auth.observer,
events: state.events.list,
}
}
export default connect(mapStateToProps)(Header);

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

@ -1,84 +1,97 @@
import React from "react";
import Head from 'next/head';
import Image from 'next/image';
import Head from "next/head";
import Image from "next/image";
import { connect } from "react-redux";
import { withRouter } from 'next/router';
import { withRouter } from "next/router";
import moment from "moment";
import { SpinnerCircular } from 'spinners-react';
import { SpinnerCircular } from "spinners-react";
import { reduxWrapper } from '../../store';
import { reduxWrapper } from "../../store";
import Header from '../components/Header';
import Footer from '../components/Footer';
import Header from "../components/Header";
import Footer from "../components/Footer";
import Company from "../components/Company";
import InnerMenu from "./components/InnerMenu";
import DownloadPdfButton from "../components/DownloadPdfButton";
import { getContractInfo, getContractAgreement, getContractRules, getFile } from "../../actions";
import {
getContractInfo,
getContractAgreement,
getContractRules,
getFile,
} from "../../actions";
class ContractPage extends React.Component
{
constructor(props)
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,
this.state =
{
date: null,
car: null,
contract_date: null,
agreement: null,
rules: null,
loading: false,
};
}
componentDidMount()
static getDerivedStateFromProps(nextProps, prevState)
{
if(!this.state.loading && this.props.number !== undefined)
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) =>
{
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(() => {});
dispatch: this.props.dispatch,
date: moment(info.date, "YYYY-MM-DD").format("DD.MM.YYYY"),
})
.then(() => {})
.catch(() => {});
})
.catch(() =>
{
.catch(() => {});
});
getContractAgreement({ dispatch: this.props.dispatch, number: this.props.number }).then(() => {
getContractAgreement({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then(() => {
this.setState({ loading: false });
}).catch(() => {});
});
})
.catch(() => {});
});
}
}
render()
render()
{
const { loading, date, car, contract_date, agreement, rules, } = this.state;
const { loading, date, car, contract_date, agreement, rules } = this.state;
const { number } = this.props;
console.log("rules", rules);
const types = {
contracts: "Договор",
redemptions: "Выкупные документы",
const types = {
contracts: "Договор",
redemptions: "Выкупные документы",
agreements: "Дополнительное соглашение",
assignments: "Договор цессии",
};
@ -87,57 +100,120 @@ class ContractPage extends React.Component
<React.Fragment>
<Head>
<title>ЛК Эволюция автолизинга</title>
<meta
name="description"
content="ЛК Эволюция автолизинга"
/>
<meta name="description" content="ЛК Эволюция автолизинга" />
</Head>
<Header { ...this.props }/>
<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 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/>
<Company />
</div>
<div className="aside_container about">
<InnerMenu number={ number } { ...this.props }/>
<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
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">
<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) =>
<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> }
<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 }` }/>
<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 }>
{ 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>
<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 }/>
<DownloadPdfButton
url={`${process.env.NEXT_PUBLIC_MAIN_SITE}${document.url}`}
filename={`${document.filename}.pdf`}
bitrix={true}
/>
</div>
)) }
</div>
@ -147,32 +223,32 @@ class ContractPage extends React.Component
</div>
</section>
</main>
<Footer/>
<Footer />
</React.Fragment>
);
}
}
function mapStateToProps(state, ownProps)
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,
}
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 {
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
number: query.number,
}
}
}
number: query.number,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractPage));
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));

473
pages/contract/compare.js Normal file
View File

@ -0,0 +1,473 @@
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 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,
};
}
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">
<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,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) =>
{
return {
props: {
//number: query.number,
number: null,
},
};
}
);
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,13 +7,26 @@ 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 = () =>
{
this.setState({
menuOpened: !this.state.menuOpened,
});
};
componentDidMount()
{
let l = 0;
let m = 0;
const menu = ["payments", "services", "agreement", "documents", "materials"];
const menu = ["payments", "services", "agreement", "documents", "materials","events","change"];
for(let i in menu)
{
@ -31,17 +44,40 @@ export default class InnerMenu extends React.Component
this.menuRef.current.scrollLeft = l - 50;
}
_getActiveLink = (route) =>
{
if (route.indexOf("/payments/") > -1) return "График платежей";
if (route.indexOf("/change/") > -1) return "Изменить график";
if (route.indexOf("/services") > -1) return "Дополнительные услуги";
if (route.indexOf("/agreement") > -1) return "Документы по договору";
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, count_events, count_fines } = this.state;
const { number } = this.props;
return (
<aside>
<ul className="aside_nav" ref={ this.menuRef }>
<button className="nav_toggle" onClick={this._handle_onToggleMenu}>
{ this.props.router && this._getActiveLink(this.props.router.route) }
</button>
<ul className={menuOpened ? "aside_nav open" : "aside_nav"} ref={ this.menuRef }>
<li>
<Link href={`/contract/${ number }/payments`} shallow>
<a className={ this.props.router && this.props.router.asPath.indexOf("payments") > -1 ? "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>
</li>
<li>
<Link href={`/contract/${ number }/services`} shallow>
@ -63,6 +99,16 @@ export default class InnerMenu extends React.Component
<a className={ this.props.router && this.props.router.asPath.indexOf("materials") > -1 ? "active" : "" }>Документы по ФСБУ 25/2018</a>
</Link>
</li>
<li>
<Link href={`/contract/${ number }/events`} shallow>
<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>
</aside>
)

View File

@ -1,32 +1,42 @@
import React from "react";
import Head from 'next/head';
import Image from 'next/image';
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 { withRouter } from "next/router";
import moment from "moment";
import 'moment/locale/ru';
import numeral from "numeral";
import { SpinnerCircular } from 'spinners-react';
import pluralize from 'pluralize-ru';
import { SpinnerCircular } from "spinners-react";
import pluralize from "pluralize-ru";
import { reduxWrapper } from '../../store';
import { reduxWrapper } from "../../store";
import Header from '../components/Header';
import Footer from '../components/Footer';
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 DateInput from "../components/DatePicker";
import DownloadPrintFormPdfButton from "../components/DownloadPrintFormPdfButton";
import DownloadFinesPdfButton from "../components/DownloadFinesPdfButton";
import FinesCalculatorForm from "./components/FinesCalculatorForm";
import { getContractInfo, getContractDocuments, getReconciliationFile } from "../../actions";
import {
getContractInfo,
getContractDocuments,
getReconciliationFile,
getContractPenalties,
} from "../../actions";
const TYPES = {
upd: "УПД по очередным платежам",
upd_avans: "УПД по авансовым платежам",
billfines: "Счета-уведомления на пени",
billgibdd: "BillGIBDD",
fines: "Штрафы ГИБДД",
upd: "УПД по очередным платежам",
upd_avans: "УПД по авансовым платежам",
billfines: "Счета-уведомления на пени",
billgibdd: "BillGIBDD",
fines: "Штрафы ГИБДД",
};
class ContractDocumentsPage extends React.Component
@ -47,203 +57,275 @@ class ContractDocumentsPage extends React.Component
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,
penalties: false,
penalties_date: moment().format("YYYY.MM.DD"),
penalties_result: undefined,
};
}
componentDidMount()
static getDerivedStateFromProps(nextProps, prevState)
{
if(!this.state.loading && this.props.number !== undefined)
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 });
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(() => {
getContractDocuments({
dispatch: this.props.dispatch,
number: this.props.number,
})
.then(() => {
this.setState({ loading: false });
}).catch(() => {});
});
})
.catch(() => {});
}
);
}
}
componentDidUpdate(prevProps, prevState)
componentDidUpdate(prevProps, prevState)
{
if(this.state.period_date_start === null)
if (this.state.period_date_start === null)
{
if(prevState.contract_date === null && this.state.contract_date !== 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;
const { reconciliation_requested, period_date_start, period_date_end } = this.state;
if(!reconciliation_requested)
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`,
getReconciliationFile({
contract: number,
date_from: date_from,
date_to: date_to,
filename: `${number}_reconciliation_${date_from}_${date_to}.pdf`,
})
.then(() =>
{
.then(() => {
this.setState({ reconciliation_requested: false });
})
.catch(() =>
{
.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 {
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 (md.isValid())
{
if(date >= valid_date_start && date <= valid_date_end)
if (date >= valid_date_start && date <= valid_date_end)
{
if(date < period_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: false,
});
}
else
{
this.setState({ period_date_start: date, reconciliation_disabled: true });
this.setState({
period_date_start: date,
reconciliation_disabled: true,
});
}
}
else
}
else
{
this.setState({ period_date_start: date, reconciliation_disabled: true });
this.setState({
period_date_start: date,
reconciliation_disabled: true,
});
}
}
else
}
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;
const {
valid_date_start,
valid_date_end,
period_date_start,
period_date_end,
} = this.state;
if(moment(date).isValid())
if (moment(date).isValid())
{
if(date >= valid_date_start && date <= valid_date_end)
if (date >= valid_date_start && date <= valid_date_end)
{
if(date > period_date_start)
if (date > period_date_start)
{
this.setState({ period_date_end: date, reconciliation_disabled: false });
}
else
this.setState({
period_date_end: date,
reconciliation_disabled: false,
});
}
else
{
this.setState({ period_date_end: date, reconciliation_disabled: true });
this.setState({
period_date_end: date,
reconciliation_disabled: true,
});
}
}
else
}
else
{
this.setState({ period_date_end: date, reconciliation_disabled: true });
this.setState({ period_date_end: date, reconciliation_disabled: true });
}
}
else
}
else
{
this.setState({ reconciliation_disabled: true });
}
}
};
_handle_onGroup = (group) =>
{
console.log("group", group);
const opened = [ ...this.state.opened ];
const opened = [...this.state.opened];
if(opened.indexOf(group) < 0)
{ opened.push(group); }
else
{ opened.splice(opened.indexOf(group), 1); }
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 !== undefined && documents !== null)
{
if(documents.length > 0)
if (documents.length > 0)
{
return (
<>
<div className={`dropdown_block bt ${ opened.indexOf(type) > -1 ? "open" : "" }`}>
<div className="block_header" onClick={ () => this._handle_onGroup(type) }>
<p>{ TYPES[type] }</p>
{ documents.length > 3 && (
<button className={`block_toggle ${ opened.indexOf(type) > -1 ? "rotate" : "" }`}></button>
<div 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>
<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" style={{ justifyContent: "center", corsor: "pointer" }} onClick={ () => this._handle_onGroup(type) }>
<p style={{ color: "#747474" }}>Еще { documents.length - 3 } { pluralize((documents.length - 3), 'документов', 'документ', 'документа', 'документов') }</p>
</div>
) }
</div>
</>
)
);
}
if(type !== "upd_avans" && type !== "billfines")
if (type !== "upd_avans" && type !== "billfines")
{
return (
<>
<div className={`dropdown_block bt ${ opened.indexOf(type) > -1 ? "open" : "" }`}>
<div className="block_header" onClick={ () => this._handle_onGroup(type) }>
<p>{ TYPES[type] }</p>
<div 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>
<div>
<p>Документов пока еще нет.</p>
<p>&nbsp;</p>
</div>
</>
);
@ -251,92 +333,80 @@ class ContractDocumentsPage extends React.Component
}
return null;
};
_handle_onPenaltiesShow = (date) =>
{
console.log("_handle_onPenaltiesShow", "date", date);
const { number } = this.props;
window.scrollTo(0, 0);
this.setState({ penalties: true, penalties_date: date, penalties_result: undefined }, () =>
{
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";
getContractPenalties({ number, date })
.then((result) =>
{
console.log("result", result);
this.setState({ penalties_result: result });
})
.catch(() =>
{
});
});
}
_renderFines = (fines, type) =>
_handle_onPenaltiesHide = () =>
{
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)
this.setState({ penalties: false, penalties_result: undefined }, () =>
{
return (
<>
<div className={`dropdown_block bt ${ opened.indexOf('fines') > -1 ? "open" : "" }`}>
<div className="block_header" onClick={ () => this._handle_onGroup('fines') }>
<p>{ TYPES[ 'fines' ] }</p>
{ fines.length > 3 && (
<button className={`block_toggle ${ opened.indexOf('fines') > -1 ? "rotate" : "" }`}></button>
) }
</div>
</div>
<div className="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>
</>
)
}
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";
return (
<>
<div className={`dropdown_block bt ${ opened.indexOf(type) > -1 ? "open" : "" }`}>
<div className="block_header" onClick={ () => this._handle_onGroup(type) }>
<p>{ TYPES[type] }</p>
</div>
</div>
<div>
<p>Штрафов не найдено.</p>
<p>&nbsp;</p>
</div>
</>
);
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, documents, period_date_start, period_date_end, valid_date_start, valid_date_end, reconciliation_requested, reconciliation_disabled, opened } = this.state;
const {
loading,
date,
car,
contract_date,
documents,
period_date_start,
period_date_end,
valid_date_start,
valid_date_end,
reconciliation_requested,
reconciliation_disabled,
opened,
penalties,
penalties_date,
penalties_result,
} = this.state;
const { number } = this.props;
console.log("documentsdocumentsdocumentsdocumentsdocuments");
@ -349,70 +419,193 @@ class ContractDocumentsPage extends React.Component
<React.Fragment>
<Head>
<title>ЛК Эволюция автолизинга</title>
<meta
name="description"
content="ЛК Эволюция автолизинга"
/>
<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)" />
<Header { ...this.props }/>
{ penalties ? (
<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" onClick={ this._handle_onPenaltiesHide }>Назад</button>
<div style={{ flexDirection: "column" }}>
<h1 className="section_title">Расчет планируемых пени</h1>
<h5 style={{ fontSize: "14px" }}>
Договор { number }
{ date !== undefined && date !== null && date !== null && (
<> от {moment(date).format("DD.MM.YYYY")}</>
) }
{ car !== undefined && car !== null
? ` - ${car.brand.name} ${car.model.name} | ${
car.reg_number !== null
? car.reg_number
: "без рег. номера"
} | ${
car.vin_number !== null
? car.vin_number
: "без VIN номера"
}`
: "" }
</h5>
</div>
) : (
<>
<div 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>
<div className="aside_container about">
<article className="fine">
<div className="fine_block">
<div className="fine_col">
<p>
<span>Пени на дату</span>
{ moment(penalties_date, "YYYY.MM.DD").format("DD.MM.YYYY") }
</p>
</div>
<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>
</>
) }
</article>
{ penalties_result === undefined ? (
<div
style={{ minHeight: 200, display: "flex", justifyContent: "center", alignItems: "center", }}
>
<SpinnerCircular size={ 90 } thickness={ 51 } speed={ 100 } color="rgba(28, 1, 169, 1)" secondaryColor="rgba(236, 239, 244, 1)" />
</div>
) : (
<>
{ penalties_result.length > 0 ? (
<div className="fine_col">
{ penalties_result.map((bill, index) => (
<p key={ index }>
{ moment(bill.dateBillout, "YYYY-MM-DD").format("MMMM") }
<span>{ numeral(bill.sumBill).format(' ., ') }&nbsp;</span>
</p>
)) }
</div>
) : (
<p>К сожалению на указанную дату расчет пени невозможен.</p>
) }
</>
)}
</div>
</article>
</div>
</div>
</div>
</section>
</main>
</section>
</main>
) : (
<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"
)}
</>
) : null}
{ documents !== undefined && documents !== null && documents.billfines !== undefined && documents.billfines !== null && documents.billfines.length > 0 && (
<FinesCalculatorForm onPenalties={ this._handle_onPenaltiesShow }/>
) }
</div>
</>
) }
</article>
</div>
</div>
</section>
</main>
) }
<Footer />
</React.Fragment>
);
@ -422,36 +615,38 @@ class ContractDocumentsPage extends React.Component
function mapStateToProps(state, ownProps)
{
return {
contract_date: state.contract.date,
date: state.contract.date,
car: state.contract.car,
documents: state.contract.documents,
}
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 {
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
number: query.number,
}
}
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 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>
</div>
{*/}
{*/
}

169
pages/contract/events.js Normal file
View File

@ -0,0 +1,169 @@
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 NotificationMessage from "../components/Events/NotificationMessage";
import { getContractInfo, getFilteredEvents } from "../../actions";
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,
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
events_loaded: nextProps.events_loaded,
filtered: nextProps.filtered,
};
}
componentDidMount()
{
getContractInfo({ dispatch: this.props.dispatch, number: this.props.number });
if(this.state.events_loaded)
{
getFilteredEvents({ dispatch: this.props.dispatch, contract: this.props.number });
}
}
componentDidUpdate(prevProps, prevState)
{
if(this.state.events_loaded && !prevState.events_loaded)
{
getFilteredEvents({ dispatch: this.props.dispatch, contract: this.props.number });
}
}
render()
{
const { loading, date, car, contract_date, events_loaded, filtered, } = 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>
{ 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,
events_loaded: state.events.loaded,
filtered: state.events.filtered,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) =>
{
return {
props: {
number: query.number,
}
}
}
);
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>
{*/
}

255
pages/contract/gibdd.js Normal file
View File

@ -0,0 +1,255 @@
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 numeral from "numeral";
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,
getContractHelpCard,
getContractInsurance,
getContractRegistration,
getContractTelematic,
} from "./../../actions";
class ContractServicesPage extends React.Component {
constructor(props) {
super(props);
this.state = {
opened: [],
date: null,
car: null,
contract_date: null,
loading: false,
helpcard: null,
insurance: null,
registration: null,
telematic: null,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
return {
date: nextProps.date,
car: nextProps.car,
contract_date: nextProps.contract_date,
helpcard: nextProps.helpcard,
insurance: nextProps.insurance,
registration: nextProps.registration,
telematic: nextProps.telematic,
};
}
componentDidMount() {
if (!this.state.loading && this.props.number !== undefined) {
this.setState({ loading: true }, () => {
getContractInfo({
dispatch: this.props.dispatch,
number: this.props.number,
});
Promise.all([
new Promise((resolve) => {
getContractHelpCard({
dispatch: this.props.dispatch,
number: this.props.number,
}).then(resolve());
}),
new Promise((resolve) => {
getContractInsurance({
dispatch: this.props.dispatch,
number: this.props.number,
}).then(resolve());
}),
new Promise((resolve) => {
getContractRegistration({
dispatch: this.props.dispatch,
number: this.props.number,
}).then(resolve());
}),
new Promise((resolve) => {
getContractTelematic({
dispatch: this.props.dispatch,
number: this.props.number,
}).then(resolve());
}),
]).then(() => {
this.setState({ loading: false });
});
});
}
}
_handle_onCard = (card) => {
const opened = [...this.state.opened];
if (opened.indexOf(card) === -1) {
opened.push(card);
} else {
opened.splice(opened.indexOf(card), 1);
}
this.setState({ opened: opened });
};
render() {
const {
opened,
loading,
date,
car,
contract_date,
helpcard,
insurance,
registration,
telematic,
} = 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">Договор {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="dropdown_blocks_list zero-margin gibdd">
<div className={`dropdown_block open`}>
<div className="block_body full">
<div className="company">
<p className="title lower">Штрафы ГИБДД</p>
<ul>
<li>
Номер постановления: <b>3432434242334</b>
</li>
<li>
Страховая: <b>3 400 000,00 </b>
</li>
<li>
Статус: <b>Оплачен</b>
</li>
<li>
Дата: <b>01/01/2020 </b>
</li>
<li>
Штраф:{" "}
<b>п. 1.15 - Несоблюдение правил парковки </b>
</li>
<li>
<div className="dosc_list medium-icon">
<div className="row">
<p className="doc_name i-pdf extension">
01/20/2020 (.PDF)
<span style={{"width":"100%"}}>
Постановление
</span>
</p>
</div>
<div className="row">
<p className="doc_name i-pdf extension">
Договор
<span style={{"width":"100%"}}>
2021_3866 от 25.06.2021
</span>
</p>
</div>
</div>
</li>
</ul>
</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,
helpcard: state.contract.helpcard,
insurance: state.contract.insurance,
registration: state.contract.registration,
telematic: state.contract.telematic,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
//number: query.number,
number: null,
},
};
}
);
export default withRouter(connect(mapStateToProps)(ContractServicesPage));

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);
@ -126,20 +131,38 @@ class ContractSchedulePage extends React.Component
<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>
<p className="section_subtitle">{ 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 номера' }` : '' }</p>
</div>
<Company/>
</div>
<div className="aside_container about">
<InnerMenu number={ number } { ...this.props }/>
<article>
<div className="avans"><p>Сумма авансовых поступлений по договору: <span style={{ whiteSpace: "nowrap" }}>{ numeral(avans).format(' ., ') }&nbsp;</span></p></div>
{ 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 style={{ border: "solid 1px red" }}>
<p>Счёт на основной долг 1: 000 </p>
<button className="button button-blue">Скачать счет</button>
</div>
<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>
<div className="contract_table schedule">
<div className="table_row table_header">
<div className="table_cell"> платежа</div>
<div className="table_cell">Дата лизингового платежа</div>
<div className="table_cell">Лизинговый платеж с НДС</div>
<div className="table_cell">НДС, 20%</div>
<div className="table_cell">Лизинговый платеж с НДС </div>
<div className="table_cell">НДС, 20% </div>
<div className="table_cell">Статус платежа</div>
<div className="table_cell">Платежное поручение</div>
</div>
@ -254,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

@ -21,7 +21,7 @@ class ContractServicesPage extends React.Component
constructor(props)
{
super(props);
this.state = {
this.state = {
opened: [],
date: null,
car: null,
@ -31,6 +31,7 @@ class ContractServicesPage extends React.Component
insurance: null,
registration: null,
telematic: null,
insurance_location_checked: false,
};
}
@ -49,6 +50,8 @@ class ContractServicesPage extends React.Component
componentDidMount()
{
console.log("document.location.hash", document.location.hash);
if(!this.state.loading && this.props.number !== undefined)
{
this.setState({ loading: true }, () =>
@ -67,6 +70,25 @@ class ContractServicesPage extends React.Component
}
}
componentDidUpdate(prevProps, prevState)
{
if(prevState.insurance === null && this.state.insurance !== null)
{
if(!this.state.insurance_location_checked)
{
this.setState({ insurance_location_checked: true }, () =>
{
if(document.location.hash.indexOf("insurance") > -1)
{
const o = [ ...this.state.opened ];
o.push("insurance");
this.setState({ opened: o });
}
});
}
}
}
_handle_onCard = (card) =>
{
const opened = [ ...this.state.opened ];
@ -87,6 +109,18 @@ class ContractServicesPage extends React.Component
const { opened, loading, date, car, contract_date, helpcard, insurance, registration, telematic, } = this.state;
const { number } = this.props;
console.log("helpcard");
console.log(helpcard);
console.log("insurance");
console.log(insurance);
console.log("registration");
console.log(registration);
console.log("telematic");
console.log(telematic);
return (
<React.Fragment>
<Head>
@ -116,7 +150,7 @@ class ContractServicesPage extends React.Component
<SpinnerCircular size={90} thickness={51} speed={100} color="rgba(28, 1, 169, 1)" secondaryColor="rgba(236, 239, 244, 1)" />
</div>
) : (
<div className="dropdown_blocks_list filled zero-margin">
<div className="dropdown_blocks_list zero-margin">
<div className={`dropdown_block ${ opened.indexOf("ratcard") > -1 ? 'open' : '' }`}>
<div className="block_header" onClick={ () => this._handle_onCard('ratcard') }>
@ -163,12 +197,28 @@ class ContractServicesPage extends React.Component
</p>
<button className="block_toggle"></button>
</div>
<div className="block_body">
<div className="block_body full">
<div className="company filled">
<p className="title">КАСКО</p>
<ul>
<li>Страховая компания: <b>Согласие</b></li>
<li>Сайт: <b>www.sogl.ru</b></li>
<li>Телефон: <b>34234324324324</b></li>
<li>Номер полиса: <b style={{color: "#1C01A9"}}>34234324324324</b></li>
<li>Период действия: <b>01/01/2020 - 01/01/2025</b></li>
<li>Страховая сумма: <b style={{ whiteSpace: "nowrap" }}>3 400 000,00 &nbsp;</b></li>
<li className="alert">Обращаем Ваше внимание, что пролонгация полиса ОСАГО на второй и последующие периоды осуществляется Лизингополучателем самостоятельно</li>
</ul>
<div className="action">
<button className="button button-blue">Скачать счет на оплату</button>
</div>
</div>
{ insurance !== undefined && insurance !== null ? (
<>
{ insurance.kasko !== undefined && insurance.kasko !== null && insurance.kasko !== "" && insurance.kasko.map !== undefined && insurance.kasko.map((entry, index) => (
<React.Fragment key={ index }>
<div className="company">
<div className= { `company ${ entry.period_type === "prolong" && "filled" }` }>
<p className="title">КАСКО</p>
<ul>
{ entry.company && (<li>Страховая компания: <b>{ entry.company }</b></li>) }
@ -177,6 +227,9 @@ class ContractServicesPage extends React.Component
{ entry.number && (<li>Номер полиса: <b>{ entry.number }</b></li>) }
{ entry.period && (<li>Период действия: <b>{ entry.period }</b></li>) }
{ entry.amount && (<li>Страховая сумма: <b style={{ whiteSpace: "nowrap" }}>{ numeral(entry.amount).format(' ., ') }&nbsp;</b></li>) }
{ entry.period_type === "prolong" && (
<li className="alert">Обращаем Ваше внимание, что пролонгация полиса КАСКО на второй и последующие периоды осуществляется Лизингополучателем самостоятельно</li>
) }
</ul>
</div>
{ entry.description && (<p>{ entry.description }</p>) }
@ -315,7 +368,8 @@ function mapStateToProps(state, ownProps)
}
}
export const getServerSideProps = reduxWrapper.getServerSideProps(store =>
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) =>
{
return {

215
pages/events.js Normal file
View File

@ -0,0 +1,215 @@
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/Events/InnerMenu";
import NotificationMessage from "./components/Events/NotificationMessage";
import { getFilteredEvents } from "../actions";
class EventsPage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
events: [],
events_loaded: false,
filtered: undefined,
type: undefined,
loading: false,
search: ""
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
events: nextProps.events,
events_loaded: nextProps.events_loaded,
filtered: nextProps.filtered,
};
}
componentDidMount()
{
}
componentDidUpdate(prevProps, prevState)
{
const hash = this.props.router.asPath.split('#')[1];
if(this.state.type !== hash)
{
this.setState({ type: hash }, () =>
{
this._filterEvents();
});
}
}
_handle_onChange_search = (value) =>
{
this.setState({ search: value });
}
_handle_onSearch = () =>
{
this._filterEvents();
}
_filterEvents = () =>
{
console.log("_filterEvents");
const { type, search } = this.state;
getFilteredEvents({ dispatch: this.props.dispatch, type, search });
}
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>
<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 {
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: {
},
};
}
);
export default withRouter(connect(mapStateToProps)(EventsPage));

View File

@ -16,8 +16,11 @@ 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 { getContractsList } from '../actions';
import AnnouncementsList from "./components/AnnouncementsList";
import { getContractsList, getImage } from '../actions';
class IndexPage extends React.Component
{
@ -25,6 +28,7 @@ class IndexPage extends React.Component
{
super(props);
this.state = {
company: {},
contracts: null,
order: "date",
sort_number: "desc",
@ -45,6 +49,7 @@ class IndexPage extends React.Component
static getDerivedStateFromProps(nextProps, prevState)
{
return {
company: nextProps.company,
contracts: nextProps.contracts,
page: nextProps.page,
pages: nextProps.pages,
@ -144,12 +149,14 @@ class IndexPage extends React.Component
render()
{
const { loading, page, pages, search, date_from, date_from_type, date_to, date_to_type, contracts, sort_number, sort_date, sort_status, all } = this.state;
const { company, loading, page, pages, search, date_from, date_from_type, date_to, date_to_type, contracts, sort_number, sort_date, sort_status, all } = this.state;
const contract_status = {
"Действующий": "opened",
"Закрыт": "closed",
};
console.log("contracts", contracts);
return (
<React.Fragment>
<Head>
@ -163,93 +170,124 @@ class IndexPage extends React.Component
<main>
<section>
<div className="clear"></div>
<div className="container">
<div className="title_wrapper">
<div className="left">
<h1 className="section_title">Личный кабинет</h1>
<div className="overflow">
<div className="container">
<div className="title_wrapper">
<div className="left">
<h1 className="section_title">Личный кабинет</h1>
</div>
<div className="right">
<Company company={ company }/>
</div>
</div>
<div className="right">
<Company/>
<AnnouncementsList />
<div className="contract_search">
<form onSubmit={ (event) => { event.preventDefault(); } }>
<div className="form_field">
<input type="search" value={ search } placeholder="Поиск" onChange={ (event) => {
this._handle_onChange_search(event.target.value);
} }/>
</div>
<div className="form_field">
{/*
<input type={ date_from_type } id="date_from" className="date_input" value="" placeholder="Дата договора от" onFocus={ () => this.setState({ date_from_type: "date" }) } onBlur={ () => { this.setState({ date_from_type: "text" }) } } onChange={ (date) => {
this._handle_onChange_date_from(date);
} }/>
<label htmlFor="date_from">Дата<br/>договора от</label>
*/}
<DateInput placeholder="Дата договора от" id={ "date_from" } onChange={ (date) => this.setState({ date_from: date }) }/>
</div>
<div className="form_field">
{/*<input type={ date_to_type } id="date_for" className="date_input" value="" placeholder="Дата договора по" onFocus={ () => this.setState({ date_from_type: "date" }) } onBlur={ () => { this.setState({ date_from_type: "text" }) } } onChange={ (date) => {
this._handle_onChange_date_to(date);
} }/>
<label htmlFor="date_for">Дата<br/>договора по</label>*/}
<DateInput placeholder="Дата договора по" id={ "date_to" } onChange={ (date) => this.setState({ date_to: date }) }/>
</div>
<button className="button" disabled={ search !== "" || date_from !== "" || date_to !== "" ? false : true } onClick={ this._handle_onSearch }>Поиск</button>
</form>
</div>
</div>
<div className="contract_search">
<form onSubmit={ (event) => { event.preventDefault(); } }>
<div className="form_field">
<input type="search" value={ search } placeholder="Поиск" onChange={ (event) => {
this._handle_onChange_search(event.target.value);
} }/>
{ loading ? (
<div className="table_row table_header" style={{ minHeight: 450, 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="form_field">
{/*
<input type={ date_from_type } id="date_from" className="date_input" value="" placeholder="Дата договора от" onFocus={ () => this.setState({ date_from_type: "date" }) } onBlur={ () => { this.setState({ date_from_type: "text" }) } } onChange={ (date) => {
this._handle_onChange_date_from(date);
} }/>
<label htmlFor="date_from">Дата<br/>договора от</label>
*/}
<DateInput placeholder="Дата договора от" id={ "date_from" } onChange={ (date) => this.setState({ date_from: date }) }/>
</div>
<div className="form_field">
{/*<input type={ date_to_type } id="date_for" className="date_input" value="" placeholder="Дата договора по" onFocus={ () => this.setState({ date_from_type: "date" }) } onBlur={ () => { this.setState({ date_from_type: "text" }) } } onChange={ (date) => {
this._handle_onChange_date_to(date);
} }/>
<label htmlFor="date_for">Дата<br/>договора по</label>*/}
<DateInput placeholder="Дата договора по" id={ "date_to" } onChange={ (date) => this.setState({ date_to: date }) }/>
</div>
<button className="button" disabled={ search !== "" || date_from !== "" || date_to !== "" ? false : true } onClick={ this._handle_onSearch }>Поиск</button>
</form>
</div>
{ loading ? (
<div className="table_row table_header" style={{ minHeight: 450, 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="contract_table">
<div className="table_row table_header">
<div className={`table_cell caret ${ sort_number === "asc" ? "reverse" : "" }`} onClick={ this._handle_onChangeSort_number }>Номер договора</div>
<div className={`table_cell caret ${ sort_date === "asc" ? "reverse" : "" }`} onClick={ this._handle_onChangeSort_date }>Дата договора</div>
<div className="table_cell">Автомобиль</div>
<div className="table_cell">Гос.номер</div>
<div className="table_cell">VIN</div>
<div className={`table_cell caret ${ sort_status === "asc" ? "reverse" : "" }`} onClick={ this._handle_onChangeSort_status }>Статус</div>
<div className="table_cell">Следующий платеж</div>
</div>
{ contracts !== null && (
<>
{ contracts.length > 0 ? contracts.map((contract, index) => (
<Link href={`/contract/${ contract.number }/payments`} key={ index }>
<div className="table_row" key={ index } style={{ cursor: "pointer" }}>
<div className="table_cell"><a>{ contract.number }</a></div>
<div className="table_cell">{ moment(contract.date).format("DD.MM.YYYY") }</div>
<div className="table_cell">{ contract.car?.brand?.name } { contract.car?.model?.name }</div>
<div className="table_cell">{ contract.car?.reg_number !== null ? contract.car?.reg_number : "Без рег. номера" }</div>
<div className="table_cell">{ contract.car?.vin_number }</div>
<div className="table_cell"><p className={ contract_status[contract.status] }>{ contract.status }</p></div>
<div className="table_cell">
{ contract.current_payment_date !== null ? (
<>{ moment(contract.current_payment_date).format("DD.MM.YYYY") }<b className="price" style={{ whiteSpace: "nowrap" }}>{ numeral(contract.current_payment_amount).format(' ., ') }&nbsp;</b></>
) : "-" }
) : (
<div className="contract_table">
<div className="table_row table_header">
<div className={`table_cell caret ${ sort_number === "asc" ? "reverse" : "" }`} onClick={ this._handle_onChangeSort_number }>Номер договора</div>
<div className={`table_cell caret ${ sort_date === "asc" ? "reverse" : "" }`} onClick={ this._handle_onChangeSort_date }>Дата договора</div>
<div className="table_cell">Автомобиль</div>
<div className="table_cell">Гос.номер / VIN</div>
<div className={`table_cell caret ${ sort_status === "asc" ? "reverse" : "" }`} onClick={ this._handle_onChangeSort_status }>Статус</div>
<div className="table_cell">Следующий платеж</div>
<div className="table_cell">Дополнительные услуги</div>
</div>
{ contracts !== null && (
<>
{ contracts.length > 0 ? contracts.map((contract, index) => (
<Link href={`/contract/${ contract.number }/payments`} key={ index }>
<div className="table_row" key={ index } style={{ cursor: "pointer" }}>
<div className="table_cell"><a>{ contract.number }</a></div>
<div className="table_cell">{ moment(contract.date).format("DD.MM.YYYY") }</div>
<div className="table_cell">{ contract.car?.brand?.name } { contract.car?.model?.name }</div>
<div className="table_cell">
{ contract.car?.reg_number !== null ? contract.car?.reg_number : "Без рег. номера" }
<span>{ contract.car?.vin_number }</span>
</div>
<div className="table_cell">
<p className={ contract_status[contract.status] }>{ contract.status }</p>
{ contract.debt_leasing !== undefined && contract.debt_leasing !== null && parseFloat(contract.debt_leasing) > 0 && (
<p className="contract_debt">
<span>Задолжность:</span>
{ numeral(contract.debt_leasing).format(' ., ') }&nbsp;
</p>
) }
{ contract.debt_penalty_fee !== undefined && contract.debt_penalty_fee !== null && parseFloat(contract.debt_penalty_fee) > 0 && (
<p className="contract_debt">
<span>Пени:</span>
{ numeral(contract.debt_penalty_fee).format(' ., ') }&nbsp;
</p>
) }
</div>
<div className="table_cell">
{ contract.current_payment_date !== null ? (
<>{ moment(contract.current_payment_date).format("DD.MM.YYYY") }<b className="price" style={{ whiteSpace: "nowrap" }}>{ numeral(contract.current_payment_amount).format(' ., ') }&nbsp;</b></>
) : "-" }
</div>
<div className="table_cell">
<div className="service_list">
{ contract.telematics_exists && <i title="Телематика" data-additional-service="1"></i> }
{ contract.rat_exists && <i title="РАТ" data-additional-service="2"></i> }
{ contract.gibddreg_exists && <i title="Регистрация в ГИБДД" data-additional-service="3"></i> }
{ contract.fuelcard_exists && <i title="Топливные карты" data-additional-service="4"></i> }
{ contract.kasko_exists && <i title="КАСКО" data-additional-service="5"></i> }
{ contract.osago_exists && <i title="ОСАГО" data-additional-service="6"></i> }
{ contract.nsib_exists && <i title="НСИБ" data-additional-service="7"></i> }
{ contract.fingap_exists && <i title="FinGAP" data-additional-service="8"></i> }
</div>
</div>
</div>
</div>
</Link>
)) : (
<div className="table_row">
<div className="table_cell">-</div>
<div className="table_cell">-</div>
<div className="table_cell">-</div>
<div className="table_cell">-</div>
<div className="table_cell">-</div>
<div className="table_cell">-</div>
<div className="table_cell">-</div>
</div>
) }
</>
) }
</div>
) }
{ !all && (
<Pagination page={ page } pages={ pages } onPage={ this._handle_onPage } onAll={ this._handle_onAll } all={ all } showAll={ true }/>
) }
<div className="table_row">
<div className="table_cell">-</div>
<div className="table_cell">-</div>
<div className="table_cell">-</div>
<div className="table_cell">-</div>
<div className="table_cell">-</div>
<div className="table_cell">-</div>
<div className="table_cell">-</div>
</div>
) }
</>
) }
</div>
) }
{ !all && (
<Pagination page={ page } pages={ pages } onPage={ this._handle_onPage } onAll={ this._handle_onAll } all={ all } showAll={ true }/>
) }
<Manager company={ company }/>
</div>
</div>
</section>
</main>
@ -262,6 +300,7 @@ class IndexPage extends React.Component
function mapStateToProps(state, ownProps)
{
return {
company: state.company,
contracts: state.contracts.list,
page: state.contracts.page,
pages: state.contracts.pages,

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));

201
pages/settings/index.js Normal file
View File

@ -0,0 +1,201 @@
import React from "react";
import Head from 'next/head';
import Image from 'next/image';
import Link from "next/link";
import cookie from 'cookie';
import { connect } from "react-redux";
import numeral from "numeral";
import pluralize from 'pluralize-ru';
import { SpinnerCircular } from 'spinners-react';
import { withRouter } from 'next/router';
import { reduxWrapper } from '../../store';
import InnerMenu from "./components/InnerMenu";
import Header from '../components/Header';
import Footer from '../components/Footer';
import Pagination from '../components/Pagination';
import Company from "../components/Company";
import { sendPhoneChangeNumber, sendPhoneChangeNumberSmsCode, setUserPhone } from '../../actions';
class IndexPage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
user: {},
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
user: nextProps.user,
};
}
render()
{
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">
<h1 className="section_title">Личный кабинет</h1>
</div>
<Company/>
</div>
<div className="aside_container about">
<InnerMenu { ...this.props }/>
<article>
<div className="settings_user_control">
<p>Настройки доступа к личному кабинету</p>
<div>
<button className="button button-blue">Добавить пользователя</button>
<button className="button button-blue">Редактировать</button>
</div>
</div>
<div className="settings_table editable">
<div className="table_header table_row">
<div className="table_cell">ФИО пользователя</div>
<div className="table_cell">Почта</div>
<div className="table_cell">Роль</div>
<div className="table_cell">Доступные организации</div>
<div className="table_cell">Статус</div>
<div className="table_cell"></div>
</div>
<div className="table_row">
<div className="table_cell" data-title="ФИО пользователя">Иванов Иван Иванович</div>
<div className="table_cell" data-title="Почта">iivanov@mail.com</div>
<div className="table_cell" data-title="Роль">Администратор</div>
<div className="table_cell" data-title="Доступные организации">Все организации</div>
<div className="table_cell" data-title="Статус">Активен</div>
<div className="table_cell delete">
<button className="delete_user" title="Удалить пользователя">Удалить</button>
</div>
</div>
<div className="table_row">
<div className="table_cell" data-title="ФИО пользователя">Иванов Иван Иванович</div>
<div className="table_cell" data-title="Почта">iivanov@mail.com</div>
<div className="table_cell" data-title="Роль">Администратор</div>
<div className="table_cell" data-title="Доступные организации">Все организации</div>
<div className="table_cell" data-title="Статус">Активен</div>
<div className="table_cell delete">
<button className="delete_user" title="Удалить пользователя">Удалить</button>
</div>
</div>
<div className="table_row editable">
<div className="table_cell" data-title="ФИО пользователя">
<input type="text" placeholder="Введите ФИО" />
</div>
<div className="table_cell" data-title="Почта">
<input type="email" placeholder="Введите почту" />
</div>
<div className="table_cell" data-title="Роль">Пользователь</div>
<div className="table_cell" data-title="Доступные организации">
<button className="settings_dropdown" data-selected="false">Выберите организацию</button>
<div className="dropdown_list opened">
<div className="list_item">
<input type="checkbox" value="" name="companies_list" id="company_1" hidden />
<label htmlFor="company_1">
Все организации
</label>
</div>
<div className="list_item">
<input type="checkbox" value="" name="companies_list" id="company_2" hidden />
<label htmlFor="company_2">
ООО Еще одно название
<span>ИНН: 12345678765 КПП: 13432-02</span>
</label>
</div>
<div className="list_item">
<input type="checkbox" value="" name="companies_list" id="company_3" hidden />
<label htmlFor="company_3">
ООО Друзья и КО
<span>ИНН: 12345678765 КПП: 13432-02</span>
</label>
</div>
</div>
</div>
<div className="table_cell" data-title="Статус">-</div>
<div className="table_cell delete">
<button className="delete_user" title="Удалить пользователя">Удалить</button>
</div>
</div>
</div>
</article>
</div>
</div>
</section>
</main>
<Footer/>
</React.Fragment>
)
}
}
function mapStateToProps(state, ownProps)
{
return {
user: state.user,
}
}
export const getServerSideProps = reduxWrapper.getServerSideProps(store =>
async ({ req, res, query }) =>
{
let props = {};
if(req.headers.cookie !== undefined)
{
const cookies = cookie.parse(req.headers?.cookie ? req.headers?.cookie : "");
if(cookies.jwt === undefined || cookies.jwt === null)
{
res.statusCode = 302;
res.setHeader('Location', `/login`);
}
else
{
//const tokenValid = await checkToken(cookies.jwt);
const tokenValid = true;
if(!tokenValid)
{
res.statusCode = 302;
res.setHeader('Location', `/login`);
}
}
}
else
{
res.statusCode = 302;
res.setHeader('Location', `/login`);
}
return { props: props };
}
);
export default withRouter(connect(mapStateToProps)(IndexPage));

View File

@ -0,0 +1,63 @@
import React from "react";
import Link from "next/link";
export default class InnerMenu extends React.Component
{
constructor(props)
{
super(props);
this.menuRef = React.createRef();
}
componentDidMount()
{
let l = 0;
let m = 0;
const menu = ["events","faq"];
for(let i in menu)
{
if(this.props.router.asPath.indexOf(menu[i]) > -1)
{
m = i;
}
}
for(let i = 0; i < m; i++)
{
l = l + this.menuRef.current.children[i].getBoundingClientRect().width;
}
this.menuRef.current.scrollLeft = l - 50;
}
_handle_onNewAppeal = () =>
{
this.props.router.push('/support/new/');
}
render()
{
const { number } = this.props;
return (
<aside className="flex">
<button className="nav_toggle">
Меню
</button>
<ul className="aside_nav" ref={ this.menuRef }>
<li>
<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={`/support/messages`} shallow>
<a className={ this.props.router && this.props.router.asPath.indexOf("messages") > -1 ? "active" : "" }>Мои обращения <span>3</span></a>
</Link>
</li>
</ul>
<button className="button button-blue new-appeal" onClick={ this._handle_onNewAppeal }>Новое обращение</button>
</aside>
)
}
}

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));

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

@ -0,0 +1,241 @@
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 { 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,
getSupportThemes,
} from "../../actions";
class ContractPage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
themes: null,
question_selected: undefined,
appeals: null,
appeal: null,
searched: null,
loading: false,
search: "",
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
themes: nextProps.themes,
appeals: nextProps.appeals,
appeal: nextProps.appeal,
searched: nextProps.searched,
};
}
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";
if (!this.state.loading)
{
this.setState({ loading: true }, () =>
{
getSupportThemes({ dispatch: this.props.dispatch })
.then(() =>
{
this.setState({ loading: false });
})
.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";
}
_handle_onQuestion = (question) =>
{
if(this.state.question_selected === question)
{
this.setState({ question_selected: undefined });
}
else
{
this.setState({ question_selected: question });
}
}
render()
{
const { loading, themes, question_selected, searched, appleals, search } = this.state;
console.log("themesthemesthemesthemesthemes");
console.log(themes);
return (
<React.Fragment>
<Head>
<title>ЛК Эволюция автолизинга</title>
<meta name="description" content="ЛК Эволюция автолизинга" />
</Head>
<Header { ...this.props } />
<main style={{ flex: 1, display: "flex", flexDirection: "column" }}>
<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>
{ loading ? (
<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>
) : (
<>
<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">
{ themes !== undefined && themes !== null && themes.map((theme) =>
(
<div className="faq_item" key={ `theme_${ theme.id }` }>
<p className="item_title">{ theme.name }</p>
<div className="dropdown_blocks_list">
{ theme.questions.map((question) =>
(
<div className={ `dropdown_block ${ parseInt(question.id, 10) === parseInt(question_selected, 10) && "open" }` } key={ `question_${ question.id }` } onClick={ () => this._handle_onQuestion(question.id) }>
<div className={ `block_header` }>
<p>{ question.title }</p>
<button></button>
</div>
<div className="block_body">
<div className="column full">
<div className="column_text_block">
<p><b>Процедура</b></p>
<p dangerouslySetInnerHTML={{ __html: question.answer }}/>
</div>
{ question.documents !== null && (
<div className="column_text_block">
<p><b>Документы</b></p>
<p dangerouslySetInnerHTML={{ __html: question.documents }}/>
</div>
) }
{ question.templates !== null && (
<div className="column_text_block">
<p><b>Шаблоны документов</b></p>
<div className="dosc_list medium-icon">
{ question.templates.map((template, index) =>
(
<div className="row" key={ `template_${ index }` }>
<p className="doc_name i-pdf extension" data-format={ template.extension }>{ template.filename }</p>
</div>
)) }
</div>
</div>
) }
<button className="button button-blue">Создать обращение</button>
</div>
</div>
</div>
)) }
</div>
</div>
)) }
</div>
{/* Результат поиска */}
{ searched !== undefined && searched !== null && searched.map((question) => (
<div className="search_list" key={ `searched_${ question.id }` }>
<div className="search_item">
<p className="item_title">{ question.theme } / { question.name }</p>
<p>К каждой теме свободное <mark>html поле для миниинструкции</mark> (со ссылками на формы документов и документы). Привязка к теме обращения в CRM</p>
</div>
</div>
)) }
</>
) }
</article>
</div>
</div>
</section>
</main>
<Footer />
</React.Fragment>
);
}
}
function mapStateToProps(state, ownProps)
{
return {
themes: state.support.themes,
searched: state.support.searched,
appeals: state.support.appeals,
appeal: state.support.appeal,
};
}
export const getServerSideProps = reduxWrapper.getServerSideProps(
(store) =>
async ({ req, res, query }) => {
return {
props: {
},
};
}
);
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));

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

@ -0,0 +1,219 @@
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() {}
_handle_onBack = () =>
{
this.props.router.push('/support/faq/');
}
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={{ alignItems: "center", flexWrap: "wrap" }}>
<button className="back" onClick={ this._handle_onBack }>Назад</button>
<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 visible">
<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 data-sm-text="Выберите файлы">
<span>Перенесите файлы на экран для быстрой загрузки или выберите файл с компьютера </span>
</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

@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z" stroke="#8E94A7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11.25 11.25H12V16.5H12.75" stroke="#8E94A7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12 9C12.6213 9 13.125 8.49632 13.125 7.875C13.125 7.25368 12.6213 6.75 12 6.75C11.3787 6.75 10.875 7.25368 10.875 7.875C10.875 8.49632 11.3787 9 12 9Z" fill="#8E94A7"/>
</svg>

After

Width:  |  Height:  |  Size: 609 B

View File

@ -0,0 +1,7 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M26.999 7L4.99902 7.00001" stroke="#A8026B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13 13V21" stroke="#A8026B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M19 13V21" stroke="#A8026B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M24.999 7.00001V26C24.999 26.2652 24.8937 26.5196 24.7061 26.7071C24.5186 26.8946 24.2642 27 23.999 27H7.99902C7.73381 27 7.47945 26.8946 7.29192 26.7071C7.10438 26.5196 6.99902 26.2652 6.99902 26V7" stroke="#A8026B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M21 7V5C21 4.46957 20.7893 3.96086 20.4142 3.58579C20.0391 3.21071 19.5304 3 19 3H13C12.4696 3 11.9609 3.21071 11.5858 3.58579C11.2107 3.96086 11 4.46957 11 5V7" stroke="#A8026B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 974 B

View File

@ -0,0 +1,4 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M22.7273 26.7262H8.91295V27.7334C8.91295 28.3961 8.37572 28.9333 7.71301 28.9333H5.00042C4.84178 28.9333 4.71317 28.8047 4.71317 28.6461V20.8709C4.71317 19.9795 5.10209 19.1324 5.77815 18.5514C5.78433 18.5461 5.78057 18.536 5.77242 18.536H5.16665C4.52233 18.536 4 18.0136 4 17.3693V16.0958C4 15.5636 4.43141 15.1322 4.96358 15.1322H5.54149C6.06462 15.1322 6.57137 15.3146 6.97451 15.648C7.03238 15.6958 7.12001 15.6746 7.14954 15.6055L8.76837 11.8203C9.24059 10.7162 10.3258 10 11.5267 10H20.1724C21.3836 10 22.476 10.7283 22.9417 11.8464L24.5316 15.6633C24.551 15.7098 24.614 15.7167 24.643 15.6755C24.8827 15.3349 25.2731 15.1322 25.6896 15.1322H26.8081C27.2823 15.1322 27.6667 15.5166 27.6667 15.9908V17.23C27.6667 17.9513 27.082 18.536 26.3607 18.536H25.6579C25.6495 18.536 25.6457 18.5466 25.6522 18.5519C26.3758 19.148 26.795 20.0363 26.795 20.9738V28.6286C26.795 28.7822 26.6705 28.9067 26.5169 28.9067H23.8895C23.2476 28.9067 22.7273 28.3864 22.7273 27.7445V26.7262Z" stroke="#8E94A7" stroke-width="2" stroke-linejoin="round"/>
<path d="M12.1709 7.17611C13.1482 6.35847 14.578 5.84277 16.1709 5.84277C17.7638 5.84277 19.1936 6.35847 20.1709 7.17611" stroke="#8E94A7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,7 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="6.3335" width="30" height="19.3333" rx="1" stroke="#8E94A7" stroke-width="2"/>
<circle cx="8.66732" cy="12.3333" r="2.33333" stroke="#8E94A7" stroke-width="2"/>
<path d="M12.3333 19.3332C12.3333 20.2941 11.9754 20.792 11.4487 21.1108C10.8377 21.4807 9.89157 21.6665 8.66667 21.6665C7.44177 21.6665 6.49562 21.4807 5.88465 21.1108C5.35792 20.792 5 20.2941 5 19.3332C5 17.3081 6.64162 15.6665 8.66667 15.6665C10.6917 15.6665 12.3333 17.3081 12.3333 19.3332Z" stroke="#8E94A7" stroke-width="2"/>
<path d="M18 12H26" stroke="#8E94A7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M18 17H26" stroke="#8E94A7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 817 B

View File

@ -0,0 +1,3 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.52941 19.5489H26.2353M5.52941 19.5489L4.02743 21.5515C3.76592 21.9002 3.75638 22.3806 4.05919 22.6941C5.59558 24.2847 9.44597 26.6665 15.8824 26.6665C22.3187 26.6665 26.1691 24.2847 27.7055 22.6941C28.0083 22.3806 27.9988 21.9002 27.7373 21.5515L26.2353 19.5489M5.52941 19.5489V18.9018M26.2353 19.5489V18.9018M26.2353 18.9018V17.4958C26.2353 17.1615 26.0659 16.8491 25.7532 16.7307C24.5619 16.2798 21.556 15.6665 15.8824 15.6665C10.2087 15.6665 7.2028 16.2798 6.01147 16.7307C5.69877 16.8491 5.52941 17.1615 5.52941 17.4958V18.9018M26.2353 18.9018H27.0148C27.3377 18.9018 27.6408 18.7458 27.8285 18.483L30.4376 14.8303C30.6407 14.546 30.6807 14.1763 30.543 13.8551L28.9867 10.2237C28.8822 9.97992 28.6852 9.78764 28.4389 9.68914L16.2537 4.81506C16.0153 4.7197 15.7494 4.7197 15.511 4.81506L3.32576 9.68914C3.07952 9.78764 2.88248 9.97992 2.77801 10.2237L1.22167 13.8551C1.08404 14.1763 1.124 14.546 1.32709 14.8303L3.93618 18.483C4.12389 18.7458 4.42696 18.9018 4.74991 18.9018H5.52941" stroke="#8E94A7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,3 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.33301 26.6667H5.3681M25.333 26.6667H20.8769M5.3681 26.6667V6C5.3681 4.89543 6.26353 4 7.3681 4H18.8769C19.9814 4 20.8769 4.89543 20.8769 6V20.7018M5.3681 26.6667H20.8769M20.8769 26.6667V20.7018M20.8769 20.7018H24.2453C25.3499 20.7018 26.2453 19.8063 26.2453 18.7018V8.38596C26.2453 7.28139 27.1407 6.38596 28.2453 6.38596H30.6663M9.54353 8.77193V12.9474H16.7014V8.77193H9.54353Z" stroke="#8E94A7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 578 B

View File

@ -0,0 +1,5 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M24.8571 1.3335H6C4.89543 1.3335 4 2.22677 4 3.33134V16.2928C4 20.1237 10.453 24.9829 14.451 27.4229C15.0533 27.7906 15.8038 27.7906 16.4062 27.4229C20.4041 24.9829 26.8571 20.1237 26.8571 16.2928V3.33134C26.8571 2.22677 25.9617 1.3335 24.8571 1.3335Z" stroke="#8E94A7" stroke-width="2" stroke-linejoin="round"/>
<path d="M12.2539 6.4126V16.5713" stroke="#8E94A7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M18.6028 6.4126L13.5234 11.492L18.6028 16.5713" stroke="#8E94A7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 682 B

View File

@ -0,0 +1,4 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M24.8571 1.3335H6C4.89543 1.3335 4 2.22677 4 3.33134V16.2928C4 20.1237 10.453 24.9829 14.451 27.4229C15.0533 27.7906 15.8038 27.7906 16.4062 27.4229C20.4041 24.9829 26.8571 20.1237 26.8571 16.2928V3.33134C26.8571 2.22677 25.9617 1.3335 24.8571 1.3335Z" stroke="#8E94A7" stroke-width="2" stroke-linejoin="round"/>
<path d="M19.5083 12.1274C19.5083 14.845 17.5745 16.8417 15.429 16.8417C13.2835 16.8417 11.3496 14.845 11.3496 12.1274C11.3496 9.40976 13.2835 7.41309 15.429 7.41309C17.5745 7.41309 19.5083 9.40976 19.5083 12.1274Z" stroke="#8E94A7" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 677 B

View File

@ -0,0 +1,4 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M24.8571 1.3335H6C4.89543 1.3335 4 2.22677 4 3.33134V16.2928C4 20.1237 10.453 24.9829 14.451 27.4229C15.0533 27.7906 15.8038 27.7906 16.4062 27.4229C20.4041 24.9829 26.8571 20.1237 26.8571 16.2928V3.33134C26.8571 2.22677 25.9617 1.3335 24.8571 1.3335Z" stroke="#8E94A7" stroke-width="2" stroke-linejoin="round"/>
<path d="M12 6.41309V11.4925M12 16.5718V11.4925M18.7725 6.41309V11.4925M18.7725 16.5718V11.4925M12 11.4925H18.7725" stroke="#8E94A7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 624 B

View File

@ -0,0 +1,5 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M24.8571 1.3335H6C4.89543 1.3335 4 2.22677 4 3.33134V16.2928C4 20.1237 10.453 24.9829 14.451 27.4229C15.0533 27.7906 15.8038 27.7906 16.4062 27.4229C20.4041 24.9829 26.8571 20.1237 26.8571 16.2928V3.33134C26.8571 2.22677 25.9617 1.3335 24.8571 1.3335Z" stroke="#8E94A7" stroke-width="2" stroke-linejoin="round"/>
<path d="M14.8906 7.78906H10.3203V10.7188H14.1406C14.4948 10.7188 14.7578 10.7995 14.9297 10.9609C15.1068 11.1172 15.1953 11.3281 15.1953 11.5938C15.1953 11.8594 15.1068 12.0703 14.9297 12.2266C14.7526 12.3828 14.4896 12.4609 14.1406 12.4609H10.3203V16.2344C10.3203 16.7135 10.2109 17.0703 9.99219 17.3047C9.77865 17.5339 9.5026 17.6484 9.16406 17.6484C8.82031 17.6484 8.53906 17.5312 8.32031 17.2969C8.10677 17.0625 8 16.7083 8 16.2344V7.42188C8 7.08854 8.04948 6.81771 8.14844 6.60938C8.2474 6.39583 8.40104 6.24219 8.60938 6.14844C8.82292 6.04948 9.09375 6 9.42188 6H14.8906C15.2604 6 15.5339 6.08333 15.7109 6.25C15.8932 6.41146 15.9844 6.625 15.9844 6.89062C15.9844 7.16146 15.8932 7.38021 15.7109 7.54688C15.5339 7.70833 15.2604 7.78906 14.8906 7.78906Z" fill="#8E94A7"/>
<path d="M23.7832 14.5078V16.1543C23.7832 16.373 23.7617 16.5488 23.7188 16.6816C23.6758 16.8105 23.5957 16.9277 23.4785 17.0332C23.3652 17.1387 23.2188 17.2402 23.0391 17.3379C22.5195 17.6191 22.0195 17.8242 21.5391 17.9531C21.0586 18.082 20.5352 18.1465 19.9688 18.1465C19.3086 18.1465 18.707 18.0449 18.1641 17.8418C17.6211 17.6387 17.1582 17.3438 16.7754 16.957C16.3926 16.5703 16.0977 16.1016 15.8906 15.5508C15.6875 15 15.5859 14.3848 15.5859 13.7051C15.5859 13.0371 15.6855 12.4258 15.8848 11.8711C16.084 11.3164 16.377 10.8457 16.7637 10.459C17.1504 10.0723 17.6211 9.77734 18.1758 9.57422C18.7305 9.36719 19.3594 9.26367 20.0625 9.26367C20.6406 9.26367 21.1523 9.3418 21.5977 9.49805C22.043 9.65039 22.4043 9.84375 22.6816 10.0781C22.959 10.3125 23.168 10.5605 23.3086 10.8223C23.4492 11.084 23.5195 11.3164 23.5195 11.5195C23.5195 11.7383 23.4375 11.9258 23.2734 12.082C23.1133 12.2344 22.9199 12.3105 22.6934 12.3105C22.5684 12.3105 22.4473 12.2812 22.3301 12.2227C22.2168 12.1641 22.1211 12.082 22.043 11.9766C21.8281 11.6406 21.6465 11.3867 21.498 11.2148C21.3496 11.043 21.1484 10.8984 20.8945 10.7812C20.6445 10.6641 20.3242 10.6055 19.9336 10.6055C19.5312 10.6055 19.1719 10.6758 18.8555 10.8164C18.5391 10.9531 18.2676 11.1543 18.041 11.4199C17.8184 11.6816 17.6465 12.0039 17.5254 12.3867C17.4082 12.7695 17.3496 13.1934 17.3496 13.6582C17.3496 14.666 17.5801 15.4414 18.041 15.9844C18.5059 16.5273 19.1523 16.7988 19.9805 16.7988C20.3828 16.7988 20.7598 16.7461 21.1113 16.6406C21.4668 16.5352 21.8262 16.3848 22.1895 16.1895V14.7949H20.8418C20.5176 14.7949 20.2715 14.7461 20.1035 14.6484C19.9395 14.5508 19.8574 14.3848 19.8574 14.1504C19.8574 13.959 19.9258 13.8008 20.0625 13.6758C20.2031 13.5508 20.3926 13.4883 20.6309 13.4883H22.6055C22.8477 13.4883 23.0527 13.5098 23.2207 13.5527C23.3887 13.5957 23.5234 13.6914 23.625 13.8398C23.7305 13.9883 23.7832 14.2109 23.7832 14.5078Z" fill="#8E94A7"/>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,5 @@
<svg width="62" height="62" viewBox="0 0 62 62" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="31" cy="31" r="31" fill="#EDEFF5"/>
<path d="M31 37C37.6274 37 43 31.6274 43 25C43 18.3726 37.6274 13 31 13C24.3726 13 19 18.3726 19 25C19 31.6274 24.3726 37 31 37Z" stroke="black" stroke-width="2" stroke-miterlimit="10"/>
<path d="M12.8105 47.4982C14.6547 44.3062 17.3064 41.6556 20.4993 39.8128C23.6922 37.9701 27.3138 37 31.0003 37C34.6868 37 38.3084 37.9702 41.5013 39.813C44.6941 41.6559 47.3458 44.3065 49.1899 47.4986" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 622 B

View File

@ -0,0 +1,3 @@
<svg width="8" height="6" viewBox="0 0 8 6" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.228 1.635C0.085 1.462 0 1.241 0 1C0 0.448 0.448 0 1 0H7C7.552 0 8 0.448 8 1C8 1.241 7.915 1.462 7.772 1.635L4.808 5.589C4.626 5.838 4.332 6 4 6C3.668 6 3.374 5.838 3.192 5.589L0.228 1.635Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 358 B

View File

@ -0,0 +1,3 @@
<svg width="12" height="7" viewBox="0 0 12 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11 1L6 6L1 1" stroke="#1C01A9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 208 B

View File

@ -0,0 +1,7 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.5 3.5L2.5 3.50001" stroke="#A8026B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.5 6.5V10.5" stroke="#A8026B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9.5 6.5V10.5" stroke="#A8026B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12.5 3.5V13C12.5 13.1326 12.4473 13.2598 12.3536 13.3536C12.2598 13.4473 12.1326 13.5 12 13.5H4C3.86739 13.5 3.74021 13.4473 3.64645 13.3536C3.55268 13.2598 3.5 13.1326 3.5 13V3.5" stroke="#A8026B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10.5 3.5V2.5C10.5 2.23478 10.3946 1.98043 10.2071 1.79289C10.0196 1.60536 9.76522 1.5 9.5 1.5H6.5C6.23478 1.5 5.98043 1.60536 5.79289 1.79289C5.60536 1.98043 5.5 2.23478 5.5 2.5V3.5" stroke="#A8026B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 982 B

View File

@ -0,0 +1,3 @@
<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M26 13C26 20.1797 20.1797 26 13 26C5.8203 26 0 20.1797 0 13C0 5.8203 5.8203 0 13 0C20.1797 0 26 5.8203 26 13ZM16.6851 11.3816L12.9996 14.5518L9.31421 11.3816L5.62878 8.21143H12.9996H20.3705L16.6851 11.3816ZM10.2859 12.9625L7.91052 10.6574L5.53516 8.35226V12.9625V17.5726L7.91052 15.2675L10.2859 12.9625ZM14.9996 13.4604L12.9991 15.1009L10.9985 13.4604L9.36875 14.7969L5.73837 17.7738H12.9991H20.2598L16.6294 14.7969L14.9996 13.4604ZM18.0886 10.6574L15.7132 12.9625L18.0886 15.2676L20.464 17.5726V12.9625V8.35226L18.0886 10.6574Z" fill="#1C01A9"/>
</svg>

After

Width:  |  Height:  |  Size: 699 B

View File

@ -0,0 +1,6 @@
<svg width="32" height="33" viewBox="0 0 32 33" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M28 7.25L16 18.25L4 7.25" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4 7.25H28V24.25C28 24.5152 27.8946 24.7696 27.7071 24.9571C27.5196 25.1446 27.2652 25.25 27 25.25H5C4.73478 25.25 4.48043 25.1446 4.29289 24.9571C4.10536 24.7696 4 24.5152 4 24.25V7.25Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.8184 16.25L4.30859 24.9674" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M27.6916 24.9675L18.1816 16.25" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 741 B

View File

@ -0,0 +1,3 @@
<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13 0C5.81813 0 0 5.81897 0 13C0 20.181 5.81897 26 13 26C20.1819 26 26 20.181 26 13C26 5.81897 20.181 0 13 0ZM19.3851 8.90626L17.2514 18.9607C17.0937 19.6736 16.6694 19.8464 16.0772 19.5109L12.8272 17.1155L11.2597 18.6252C11.0869 18.798 10.9401 18.9448 10.6046 18.9448L10.8353 15.6369L16.8581 10.1954C17.1206 9.96471 16.8002 9.83387 16.4538 10.0645L9.01026 14.7504L5.80219 13.749C5.10523 13.5292 5.08929 13.052 5.94897 12.7165L18.4826 7.88303C19.0647 7.67335 19.573 8.02477 19.3843 8.90542L19.3851 8.90626Z" fill="#1C01A9"/>
</svg>

After

Width:  |  Height:  |  Size: 637 B

View File

@ -0,0 +1,4 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 28H20" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.02571 12.9999C7.02406 11.8139 7.25715 10.6393 7.71157 9.54386C8.16598 8.44838 8.83272 7.45367 9.67336 6.61707C10.514 5.78047 11.5119 5.11852 12.6096 4.66938C13.7072 4.22025 14.8829 3.99281 16.0689 4.00017C21.0176 4.03696 24.9759 8.15034 24.9759 13.1129V13.9999C24.9759 18.4769 25.9126 21.0748 26.7376 22.4947C26.8264 22.6464 26.8737 22.8189 26.8747 22.9947C26.8756 23.1705 26.8302 23.3435 26.7429 23.4962C26.6557 23.6488 26.5297 23.7758 26.3778 23.8642C26.2258 23.9527 26.0532 23.9995 25.8774 23.9999H6.12329C5.94744 23.9995 5.77482 23.9526 5.62284 23.8642C5.47087 23.7757 5.34491 23.6487 5.25767 23.496C5.17044 23.3434 5.12502 23.1704 5.12599 22.9945C5.12696 22.8187 5.17429 22.6462 5.26321 22.4945C6.08862 21.0745 7.02571 18.4766 7.02571 13.9999L7.02571 12.9999Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,6 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="16" r="15.5" stroke="#0C0C0C"/>
<path d="M18.7002 8.4375C19.8657 8.75095 20.9283 9.36513 21.7817 10.2185C22.6351 11.0719 23.2493 12.1346 23.5628 13.3001" stroke="#0C0C0C" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M17.9883 11.0945C18.6876 11.2825 19.3252 11.6511 19.8372 12.1631C20.3492 12.6751 20.7178 13.3127 20.9058 14.012" stroke="#0C0C0C" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12.9472 15.7264C13.6603 17.1843 14.8421 18.3608 16.3033 19.0673C16.4102 19.1179 16.5285 19.1399 16.6465 19.1309C16.7644 19.122 16.878 19.0825 16.9761 19.0164L19.1276 17.5817C19.2228 17.5182 19.3322 17.4795 19.4461 17.4691C19.56 17.4586 19.6747 17.4767 19.7798 17.5218L23.8049 19.2468C23.9416 19.3049 24.0558 19.4058 24.1302 19.5344C24.2045 19.663 24.2351 19.8123 24.2173 19.9598C24.09 20.9553 23.6043 21.8703 22.851 22.5335C22.0978 23.1966 21.1286 23.5625 20.125 23.5626C17.0253 23.5626 14.0525 22.3312 11.8607 20.1394C9.66886 17.9475 8.4375 14.9748 8.4375 11.8751C8.43755 10.8715 8.80342 9.90228 9.46659 9.14901C10.1298 8.39574 11.0448 7.91002 12.0403 7.7828C12.1877 7.76495 12.337 7.79551 12.4656 7.86989C12.5942 7.94426 12.6952 8.05841 12.7533 8.19514L14.4798 12.2237C14.5244 12.3279 14.5426 12.4415 14.5328 12.5545C14.5229 12.6674 14.4852 12.7762 14.4231 12.871L12.9934 15.0555C12.9284 15.1538 12.8899 15.2673 12.8818 15.3848C12.8737 15.5024 12.8962 15.6201 12.9472 15.7264V15.7264Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,3 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.5595 15.6018C12.5968 17.7225 14.3158 19.4336 16.4412 20.4613C16.5967 20.535 16.7687 20.5669 16.9403 20.5539C17.1119 20.5409 17.2771 20.4835 17.4198 20.3872L20.5492 18.3004C20.6877 18.2082 20.8469 18.1518 21.0126 18.1366C21.1782 18.1214 21.3451 18.1478 21.498 18.2133L27.3526 20.7224C27.5515 20.8069 27.7175 20.9537 27.8257 21.1408C27.9339 21.3278 27.9783 21.545 27.9524 21.7595C27.7673 23.2075 27.0608 24.5384 25.9652 25.503C24.8695 26.4676 23.4598 26.9998 22 26.9999C17.4913 26.9999 13.1673 25.2088 9.97919 22.0207C6.79107 18.8326 5 14.5086 5 9.99988C5.00008 8.5401 5.53224 7.13039 6.49685 6.03472C7.46146 4.93905 8.79237 4.23255 10.2404 4.0475C10.4549 4.02154 10.672 4.066 10.8591 4.17418C11.0461 4.28236 11.193 4.4484 11.2775 4.64728L13.7888 10.507C13.8537 10.6586 13.8802 10.8239 13.8658 10.9881C13.8514 11.1524 13.7967 11.3106 13.7064 11.4485L11.6268 14.626C11.5322 14.769 11.4762 14.934 11.4644 15.105C11.4526 15.2761 11.4854 15.4472 11.5595 15.6018V15.6018Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Some files were not shown because too many files have changed in this diff Show More