tasks 16.12.2021 - 27.12.2021, auth, settings, fines
This commit is contained in:
parent
57681ba377
commit
52c567df49
@ -76,7 +76,7 @@ export const sendLoginFormPhone = ({ phone }) =>
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/auth/phone/check`, { phone })
|
||||
.then((response) =>
|
||||
{
|
||||
console.log("sendTermsForm RESPONSE");
|
||||
console.log("sendLoginFormPhone RESPONSE");
|
||||
console.log(response.data);
|
||||
|
||||
if(response.data)
|
||||
@ -108,7 +108,7 @@ export const sendSmsCode = ({ dispatch, phone, code }) =>
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/auth/phone/code`, { phone, code })
|
||||
.then((response) =>
|
||||
{
|
||||
console.log("checkSmsCode RESPONSE");
|
||||
console.log("sendSmsCode RESPONSE");
|
||||
console.log(response.data);
|
||||
|
||||
if(response.data.status === "success")
|
||||
|
||||
@ -294,4 +294,28 @@ export const getContractRules = ({ dispatch, date, }) =>
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export const getContractMaterials = ({ dispatch, }) =>
|
||||
{
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/materials`, {
|
||||
},
|
||||
{
|
||||
withCredentials: true,
|
||||
})
|
||||
.then(async (response) =>
|
||||
{
|
||||
console.log("getContractMaterials", "response.data", response.data);
|
||||
dispatch({ type: actionTypes.CONTRACT_MATERIALS, data: { materials: response.data.materials } });
|
||||
|
||||
resolve();
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.error(error);
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -70,6 +70,54 @@ export const getPrintFile = ({ contract, num, type, date, filename }) =>
|
||||
});
|
||||
}
|
||||
|
||||
export const getFineBeforeAccrualFile = ({ contract, num, filename }) =>
|
||||
{
|
||||
console.log("getFile");
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
axios.get(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/file/fine-before-accrual`, {
|
||||
params: { contract, num, },
|
||||
responseType: 'blob',
|
||||
})
|
||||
.then((response) =>
|
||||
{
|
||||
fileDownload(response.data, filename);
|
||||
resolve();
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.log("error");
|
||||
console.error(error);
|
||||
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export const getFineAfterAccrualFile = ({ contract, num, filename }) =>
|
||||
{
|
||||
console.log("getFile");
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
axios.get(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/file/fine-after-accrual`, {
|
||||
params: { contract, num, },
|
||||
responseType: 'blob',
|
||||
})
|
||||
.then((response) =>
|
||||
{
|
||||
fileDownload(response.data, filename);
|
||||
resolve();
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.log("error");
|
||||
console.error(error);
|
||||
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export const getReconciliationFile = ({ contract, date_from, date_to, filename }) =>
|
||||
{
|
||||
console.log("getFile");
|
||||
|
||||
@ -5,4 +5,5 @@ export * from './calendarActions';
|
||||
export * from './companyActions';
|
||||
export * from './fileActions';
|
||||
export * from './navigationActions';
|
||||
export * from './formsActions';
|
||||
export * from './formsActions';
|
||||
export * from './settingsActions';
|
||||
141
actions/recoveryActions.js
Normal file
141
actions/recoveryActions.js
Normal file
@ -0,0 +1,141 @@
|
||||
import axios from 'axios';
|
||||
import { Cookies } from 'react-cookie';
|
||||
import Router from 'next/router';
|
||||
import moment from 'moment';
|
||||
|
||||
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 sendEmailCheck = ({ email }) =>
|
||||
{
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/recovery/check`, { email })
|
||||
.then((response) =>
|
||||
{
|
||||
console.log("sendEmailCheck RESPONSE");
|
||||
console.log(response.data);
|
||||
|
||||
if(response.data)
|
||||
{
|
||||
console.log("DATA? ");
|
||||
resolve();
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("DATA ! ");
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.error("error");
|
||||
console.error(error);
|
||||
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export const sendEmailCode = ({ email, code }) =>
|
||||
{
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/recovery/code`, { email, code })
|
||||
.then((response) =>
|
||||
{
|
||||
console.log("checkSmsCode RESPONSE");
|
||||
console.log(response.data);
|
||||
|
||||
if(response.data.status === "success")
|
||||
{
|
||||
resolve();
|
||||
}
|
||||
else
|
||||
{
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.error("error");
|
||||
console.error(error);
|
||||
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export const sendPassword = ({ email, code, password, password_repeat }) =>
|
||||
{
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/recovery/password`, { email, code, password, password_repeat })
|
||||
.then((response) =>
|
||||
{
|
||||
console.log("sendPassword RESPONSE");
|
||||
console.log(response.data);
|
||||
|
||||
if(response.data.status === "success")
|
||||
{
|
||||
resolve();
|
||||
}
|
||||
else
|
||||
{
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.error("error");
|
||||
console.error(error);
|
||||
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export const sendNewPassword = ({ password, new_password, new_password_repeat }) =>
|
||||
{
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/change/password`, { password, new_password, new_password_repeat })
|
||||
.then((response) =>
|
||||
{
|
||||
console.log("sendNewPassword RESPONSE");
|
||||
console.log(response.data);
|
||||
|
||||
if(response.data.status === "success")
|
||||
{
|
||||
resolve();
|
||||
}
|
||||
else
|
||||
{
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.error("error");
|
||||
console.error(error);
|
||||
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
119
actions/settingsActions.js
Normal file
119
actions/settingsActions.js
Normal file
@ -0,0 +1,119 @@
|
||||
import axios from 'axios';
|
||||
import { Cookies } from 'react-cookie';
|
||||
import Router from 'next/router';
|
||||
import moment from 'moment';
|
||||
|
||||
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 sendPhoneChangeNumber = ({ email, phone }) =>
|
||||
{
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/change/phone/send`, { email, phone })
|
||||
.then((response) =>
|
||||
{
|
||||
console.log("\n", "sendLoginFormPhone", "RESPONSE");
|
||||
console.log(response.data);
|
||||
|
||||
if(response.data)
|
||||
{
|
||||
console.log("DATA? ");
|
||||
resolve();
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("DATA ! ");
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.log("DATA !!! ");
|
||||
console.log("error");
|
||||
console.error(error);
|
||||
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export const sendPhoneChangeNumberSmsCode = ({ phone, code }) =>
|
||||
{
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/change/phone/code`, { phone, code })
|
||||
.then((response) =>
|
||||
{
|
||||
console.log("\n", "sendPhoneChangeNumberSmsCode", "RESPONSE");
|
||||
console.log(response.data);
|
||||
|
||||
if(response.data.status === "success")
|
||||
{
|
||||
resolve();
|
||||
}
|
||||
else
|
||||
{
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.error("error");
|
||||
console.error(error);
|
||||
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export const sendNewPassword = ({ email, password, new_password, new_password_repeat }) =>
|
||||
{
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/change/password`, { email, password, new_password, new_password_repeat })
|
||||
.then((response) =>
|
||||
{
|
||||
console.log("\n", "sendNewPassword", "RESPONSE");
|
||||
console.log(response.data);
|
||||
|
||||
if(response.data)
|
||||
{
|
||||
resolve(response.data);
|
||||
}
|
||||
else
|
||||
{
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.error("error");
|
||||
console.error(error);
|
||||
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export const setUserPhone = ({ dispatch, user }) =>
|
||||
{
|
||||
console.log("setUserPhone", dispatch, user);
|
||||
dispatch({ type: actionTypes.USER, data: user });
|
||||
}
|
||||
@ -12,4 +12,5 @@ export const CONTRACT_TELEMATIC = 'CONTRACT_TELEMATIC';
|
||||
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';
|
||||
3003
css/main/style.css
3003
css/main/style.css
File diff suppressed because one or more lines are too long
@ -3313,6 +3313,24 @@ main .dropdown_blocks_list .dropdown_block .block_body {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fines_detail {
|
||||
margin: 30px 0;
|
||||
|
||||
p {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
ul {
|
||||
max-width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
li {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown_block + .dosc_list {
|
||||
|
||||
16
css/var.css
16
css/var.css
@ -464,3 +464,19 @@ div {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
}
|
||||
.rw-calendar-btn-view {
|
||||
font-weight: bold;
|
||||
font-size: 12px !important;
|
||||
}
|
||||
@media all and (max-width: 768px) {
|
||||
.rw-calendar-btn-view {
|
||||
font-size: 12px !important;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 1600px) and (min-width: 1280px) {
|
||||
.rw-calendar-btn-view {
|
||||
font-size: 12px !important;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
15
css/var.less
15
css/var.less
@ -493,4 +493,19 @@ div {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rw-calendar-btn-view {
|
||||
font-weight: bold;
|
||||
font-size: 12px !important;
|
||||
|
||||
@media all and (max-width: 768px) {
|
||||
font-size: 12px !important;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
@media (max-width: 1600px) and (min-width: 1280px) {
|
||||
font-size: 12px !important;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
@ -44,18 +44,22 @@ module.exports = withImages(withFonts(withLess({
|
||||
{
|
||||
source: "/contract/:number/payments",
|
||||
destination: "/contract",
|
||||
},
|
||||
},
|
||||
{
|
||||
source: "/contract/:number/agreement",
|
||||
destination: "/contract/agreement",
|
||||
},
|
||||
},
|
||||
{
|
||||
source: "/contract/:number/services",
|
||||
destination: "/contract/services",
|
||||
},
|
||||
},
|
||||
{
|
||||
source: "/contract/:number/documents",
|
||||
destination: "/contract/documents",
|
||||
},
|
||||
{
|
||||
source: "/contract/:number/materials",
|
||||
destination: "/contract/materials",
|
||||
}
|
||||
//{
|
||||
//source: "/about/reviews/:page(\\d{1,})",
|
||||
|
||||
@ -15,7 +15,8 @@ const redis = new Redis(process.env.REDIS_URL);
|
||||
export default async function handler(req, res)
|
||||
{
|
||||
await cors(req, res);
|
||||
const { phone } = req.body;
|
||||
let { phone } = req.body;
|
||||
phone = phone.replace(/[^0-9.]/g, '');
|
||||
|
||||
const response = await new Promise((resolve, reject) =>
|
||||
{
|
||||
|
||||
@ -13,9 +13,11 @@ const redis = new Redis(process.env.REDIS_URL);
|
||||
export default async function handler(req, res)
|
||||
{
|
||||
await cors(req, res);
|
||||
const { phone, code } = req.body;
|
||||
let { phone, code } = req.body;
|
||||
let token = "";
|
||||
|
||||
phone = phone.replace(/[^0-9.]/g, '');
|
||||
|
||||
const key = md5(`sms_code_${ phone }`);
|
||||
let existed_data = await redis.get(key);
|
||||
|
||||
|
||||
50
pages/api/change/password.js
Normal file
50
pages/api/change/password.js
Normal file
@ -0,0 +1,50 @@
|
||||
import axios from 'axios';
|
||||
import { Cookies } from 'react-cookie';
|
||||
import cookie from 'cookie';
|
||||
import moment from 'moment';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import Redis from 'ioredis';
|
||||
import md5 from 'md5';
|
||||
|
||||
import { cors } from '../../../lib/cors';
|
||||
|
||||
const redis = new Redis(process.env.REDIS_URL);
|
||||
|
||||
export default async function handler(req, res)
|
||||
{
|
||||
await cors(req, res);
|
||||
const { email, password, new_password, new_password_repeat } = req.body;
|
||||
|
||||
const response = await new Promise((resolve, reject) =>
|
||||
{
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_API_HOST }/api/account/change/password/`, {
|
||||
email,
|
||||
password,
|
||||
new_password,
|
||||
new_password_repeat
|
||||
})
|
||||
.then((api_response) =>
|
||||
{
|
||||
console.log("RESPONSE");
|
||||
console.log(api_response.data);
|
||||
|
||||
resolve(api_response.data);
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.log("error");
|
||||
console.error(error);
|
||||
|
||||
res.status(403).json();
|
||||
});
|
||||
});
|
||||
|
||||
if(response)
|
||||
{
|
||||
res.status(200).json(response);
|
||||
}
|
||||
else
|
||||
{
|
||||
res.status(403).json();
|
||||
}
|
||||
}
|
||||
81
pages/api/change/phone/code.js
Normal file
81
pages/api/change/phone/code.js
Normal file
@ -0,0 +1,81 @@
|
||||
|
||||
import axios from 'axios';
|
||||
import { Cookies } from 'react-cookie';
|
||||
import cookie from 'cookie';
|
||||
import moment from 'moment';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import Redis from 'ioredis';
|
||||
import md5 from 'md5';
|
||||
|
||||
import { cors } from '../../../../lib/cors';
|
||||
|
||||
const redis = new Redis(process.env.REDIS_URL);
|
||||
|
||||
export default async function handler(req, res)
|
||||
{
|
||||
await cors(req, res);
|
||||
let { phone, code } = req.body;
|
||||
let token = "";
|
||||
|
||||
phone = phone.replace(/[^0-9.]/g, '');
|
||||
|
||||
const key = md5(`phone_change_sms_code_${ phone }`);
|
||||
let existed_data = await redis.get(key);
|
||||
|
||||
if(existed_data !== null)
|
||||
{
|
||||
const existed_data_json = JSON.parse(existed_data);
|
||||
|
||||
if(existed_data_json.code === code)
|
||||
{
|
||||
console.log("existed_data_json");
|
||||
console.log(existed_data_json);
|
||||
console.log("*".repeat(50));
|
||||
|
||||
const cookies = cookie.parse(req.headers?.cookie ? req.headers?.cookie : "");
|
||||
const response = await new Promise((resolve, reject) =>
|
||||
{
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_API_HOST }/api/account/change/phone/`, {
|
||||
email: existed_data_json.email,
|
||||
phone,
|
||||
}, {
|
||||
headers: {
|
||||
"Authorization": `Bearer ${ cookies.jwt }`,
|
||||
},
|
||||
})
|
||||
.then((api_response) =>
|
||||
{
|
||||
console.log("RESPONSE FROM API");
|
||||
console.log(api_response.data);
|
||||
|
||||
resolve({ status: "success" });
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.log("RESPONSE FROM API");
|
||||
console.error("error");
|
||||
console.error(error);
|
||||
|
||||
resolve({ status: "error" });
|
||||
});
|
||||
});
|
||||
|
||||
if(response.status === "success")
|
||||
{
|
||||
res.status(200).json({ status: "success", });
|
||||
}
|
||||
else
|
||||
{
|
||||
res.status(403).json();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res.status(403).json();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res.status(403).json();
|
||||
}
|
||||
}
|
||||
42
pages/api/change/phone/send.js
Normal file
42
pages/api/change/phone/send.js
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
// 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 Redis from 'ioredis';
|
||||
import md5 from 'md5';
|
||||
|
||||
import { cors } from '../../../../lib/cors';
|
||||
const SmsCenter = require('../../../../lib/SmsCenter');
|
||||
|
||||
const redis = new Redis(process.env.REDIS_URL);
|
||||
|
||||
export default async function handler(req, res)
|
||||
{
|
||||
await cors(req, res);
|
||||
let { email, phone } = req.body;
|
||||
phone = phone.replace(/[^0-9.]/g, '');
|
||||
|
||||
let code = ``;
|
||||
for(let i = 0; i < 6; i++) { code = `${code}${Math.floor(Math.random()*10)}`; }
|
||||
|
||||
const key = md5(`phone_change_sms_code_${ phone }`);
|
||||
await redis.set(key, JSON.stringify({
|
||||
email, phone, code
|
||||
}), 'EX', 300);
|
||||
|
||||
const smsResult = await SmsCenter.send(phone, code)
|
||||
.then(() =>
|
||||
{
|
||||
res.status(200).json({
|
||||
status: "success",
|
||||
});
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.error("SmsCenter.send", "catch");
|
||||
res.status(404).json();
|
||||
});
|
||||
}
|
||||
52
pages/api/contract/materials.js
Normal file
52
pages/api/contract/materials.js
Normal file
@ -0,0 +1,52 @@
|
||||
// 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/materials/`, {
|
||||
})
|
||||
.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
52
pages/api/file/fine-after-accrual.js
Normal file
52
pages/api/file/fine-after-accrual.js
Normal file
@ -0,0 +1,52 @@
|
||||
// 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)
|
||||
{
|
||||
var client_jwt_decoded = jwt.verify(cookies.jwt, process.env.JWT_SECRET_CLIENT);
|
||||
var crm_jwt = jwt.sign(client_jwt_decoded, process.env.JWT_SECRET_CRM, { noTimestamp: true });
|
||||
|
||||
try
|
||||
{
|
||||
axios.get(`${ process.env.CRM_API_HOST }/lk/Contract/GetInvoiceFineGIBDDAfterAccrual/`, {
|
||||
params: { ...client_jwt_decoded, contract_number: req.query.contract, decree_number: req.query.num, },
|
||||
responseType: 'arraybuffer',
|
||||
headers: {
|
||||
"Authorization": `Bearer ${ crm_jwt }`,
|
||||
}
|
||||
})
|
||||
.then((crm_response) =>
|
||||
{
|
||||
res.status(200).send(crm_response.data);
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.error(error);
|
||||
res.status(500);
|
||||
});
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
console.error(e);
|
||||
res.status(500);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res.status(403);
|
||||
}
|
||||
}
|
||||
}
|
||||
52
pages/api/file/fine-before-accrual.js
Normal file
52
pages/api/file/fine-before-accrual.js
Normal file
@ -0,0 +1,52 @@
|
||||
// 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)
|
||||
{
|
||||
var client_jwt_decoded = jwt.verify(cookies.jwt, process.env.JWT_SECRET_CLIENT);
|
||||
var crm_jwt = jwt.sign(client_jwt_decoded, process.env.JWT_SECRET_CRM, { noTimestamp: true });
|
||||
|
||||
try
|
||||
{
|
||||
axios.get(`${ process.env.CRM_API_HOST }/lk/Contract/GetInvoiceFineGIBDDBeforeAccrual/`, {
|
||||
params: { ...client_jwt_decoded, contract_number: req.query.contract, decree_number: req.query.num, },
|
||||
responseType: 'arraybuffer',
|
||||
headers: {
|
||||
"Authorization": `Bearer ${ crm_jwt }`,
|
||||
}
|
||||
})
|
||||
.then((crm_response) =>
|
||||
{
|
||||
res.status(200).send(crm_response.data);
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.error(error);
|
||||
res.status(500);
|
||||
});
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
console.error(e);
|
||||
res.status(500);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res.status(403);
|
||||
}
|
||||
}
|
||||
}
|
||||
61
pages/api/recovery/check.js
Normal file
61
pages/api/recovery/check.js
Normal file
@ -0,0 +1,61 @@
|
||||
// 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 Redis from 'ioredis';
|
||||
import md5 from 'md5';
|
||||
|
||||
import { cors } from '../../../lib/cors';
|
||||
|
||||
const redis = new Redis(process.env.REDIS_URL);
|
||||
|
||||
export default async function handler(req, res)
|
||||
{
|
||||
await cors(req, res);
|
||||
const { email } = req.body;
|
||||
|
||||
let code = ``;
|
||||
for(let i = 0; i < 10; i++) { code = `${code}${Math.floor(Math.random()*10)}`; }
|
||||
|
||||
const response = await new Promise((resolve, reject) =>
|
||||
{
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_API_HOST }/api/account/recovery/email/`, {
|
||||
email,
|
||||
code,
|
||||
})
|
||||
.then((api_response) =>
|
||||
{
|
||||
console.log("RESPONSE");
|
||||
console.log(api_response.data);
|
||||
|
||||
resolve(api_response.data);
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.log("error");
|
||||
console.error(error);
|
||||
|
||||
reject();
|
||||
});
|
||||
});
|
||||
|
||||
console.log("CHECK response");
|
||||
console.log(response);
|
||||
console.log("-".repeat(50));
|
||||
|
||||
if(response.status === "success")
|
||||
{
|
||||
const key = md5(`email_code_${ email }`);
|
||||
await redis.set(key, JSON.stringify({ code }), 'EX', 300);
|
||||
|
||||
res.status(200).json({
|
||||
status: "success",
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
res.status(404).json();
|
||||
}
|
||||
}
|
||||
40
pages/api/recovery/code.js
Normal file
40
pages/api/recovery/code.js
Normal file
@ -0,0 +1,40 @@
|
||||
import axios from 'axios';
|
||||
import { Cookies } from 'react-cookie';
|
||||
import cookie from 'cookie';
|
||||
import moment from 'moment';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import Redis from 'ioredis';
|
||||
import md5 from 'md5';
|
||||
|
||||
import { cors } from '../../../lib/cors';
|
||||
|
||||
const redis = new Redis(process.env.REDIS_URL);
|
||||
|
||||
export default async function handler(req, res)
|
||||
{
|
||||
await cors(req, res);
|
||||
const { email, code, } = req.body;
|
||||
let token = "";
|
||||
|
||||
const key = md5(`email_code_${ email }`);
|
||||
let existed_data = await redis.get(key);
|
||||
|
||||
if(existed_data !== null)
|
||||
{
|
||||
const existed_data_json = JSON.parse(existed_data);
|
||||
|
||||
if(existed_data_json.code === code)
|
||||
{
|
||||
await redis.set(key, JSON.stringify({ code }), 'EX', 900);
|
||||
res.status(200).json({ status: "success" });
|
||||
}
|
||||
else
|
||||
{
|
||||
res.status(403).json();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res.status(403).json();
|
||||
}
|
||||
}
|
||||
66
pages/api/recovery/password.js
Normal file
66
pages/api/recovery/password.js
Normal file
@ -0,0 +1,66 @@
|
||||
import axios from 'axios';
|
||||
import { Cookies } from 'react-cookie';
|
||||
import cookie from 'cookie';
|
||||
import moment from 'moment';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import Redis from 'ioredis';
|
||||
import md5 from 'md5';
|
||||
|
||||
import { cors } from '../../../lib/cors';
|
||||
|
||||
const redis = new Redis(process.env.REDIS_URL);
|
||||
|
||||
export default async function handler(req, res)
|
||||
{
|
||||
await cors(req, res);
|
||||
const { email, code, password, password_repeat } = req.body;
|
||||
let token = "";
|
||||
|
||||
const key = md5(`email_code_${ email }`);
|
||||
let existed_data = await redis.get(key);
|
||||
|
||||
if(existed_data !== null)
|
||||
{
|
||||
const existed_data_json = JSON.parse(existed_data);
|
||||
|
||||
if(existed_data_json.code === code && password === password_repeat)
|
||||
{
|
||||
const response = await new Promise((resolve, reject) =>
|
||||
{
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_API_HOST }/api/account/recovery/password/`, {
|
||||
email,
|
||||
code,
|
||||
password,
|
||||
password_repeat
|
||||
})
|
||||
.then((api_response) =>
|
||||
{
|
||||
console.log("RESPONSE");
|
||||
console.log(api_response.data);
|
||||
|
||||
resolve(api_response.data);
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
console.log("error");
|
||||
console.error(error);
|
||||
|
||||
res.status(403).json();
|
||||
});
|
||||
});
|
||||
|
||||
if(response)
|
||||
{
|
||||
res.status(200).json({ status: "success" });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res.status(403).json();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res.status(403).json();
|
||||
}
|
||||
}
|
||||
53
pages/components/DownloadFinesPdfButton/index.js
Normal file
53
pages/components/DownloadFinesPdfButton/index.js
Normal file
@ -0,0 +1,53 @@
|
||||
import React from "react";
|
||||
import { SpinnerCircular } from 'spinners-react';
|
||||
|
||||
import { getFineBeforeAccrualFile, getFineAfterAccrualFile } from "../../../actions";
|
||||
|
||||
export default class DownloadFinesPdfButton extends React.Component
|
||||
{
|
||||
constructor(props)
|
||||
{
|
||||
super(props);
|
||||
this.state = {
|
||||
downloading: false,
|
||||
};
|
||||
}
|
||||
|
||||
_handle_onDownloadFile = () =>
|
||||
{
|
||||
const { contract, num, filename, before } = this.props;
|
||||
const { downloading } = this.state;
|
||||
|
||||
if(!downloading)
|
||||
{
|
||||
this.setState({ downloading: true }, () =>
|
||||
{
|
||||
if(before)
|
||||
{
|
||||
getFineBeforeAccrualFile({ contract, num, filename })
|
||||
.then(() => { this.setState({ downloading: false }); })
|
||||
.catch(() => { this.setState({ downloading: false }); });
|
||||
}
|
||||
else
|
||||
{
|
||||
getFineAfterAccrualFile({ contract, num, filename })
|
||||
.then(() => { this.setState({ downloading: false }); })
|
||||
.catch(() => { this.setState({ downloading: false }); });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render()
|
||||
{
|
||||
const { downloading } = this.state;
|
||||
|
||||
return (
|
||||
<a style={{ cursor: "pointer" }} className="button button-blue" onClick={ () => { this._handle_onDownloadFile() }}>
|
||||
{ downloading ? (
|
||||
<SpinnerCircular size={24} thickness={100} speed={100} color="rgba(255, 255, 255, 1)" secondaryColor="rgba(255, 255, 255, 0.5)" />
|
||||
) : "Скачать" }
|
||||
</a>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -24,7 +24,7 @@ export default class Header extends React.Component
|
||||
{
|
||||
if(route === "/") return "Договоры";
|
||||
if(route.indexOf("/documents/") > -1) return "Взаиморасчеты и закрывающие документы";
|
||||
if(route === "/settings") return "Настройки";
|
||||
if(route.indexOf("/settings/") > -1) return "Настройки";
|
||||
if(route.indexOf("/contract") === 0) return "Договоры";
|
||||
|
||||
return null;
|
||||
@ -61,8 +61,8 @@ export default class Header extends React.Component
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/settings/" shallow>
|
||||
<a className={ this.props.router && this.props.router.route === "/settings" ? "active" : "" }>Настройки</a>
|
||||
<Link href="/settings/phone/" shallow>
|
||||
<a className={ this.props.router && this.props.router.route.indexOf("/settings/") === 0 ? "active" : "" }>Настройки</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
|
||||
@ -122,7 +122,7 @@ class ContractPage extends React.Component
|
||||
<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 } от { file.date }</span>
|
||||
<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 }` }/>
|
||||
|
||||
@ -13,7 +13,7 @@ export default class InnerMenu extends React.Component
|
||||
{
|
||||
let l = 0;
|
||||
let m = 0;
|
||||
const menu = ["payments", "services", "agreement", "documents"];
|
||||
const menu = ["payments", "services", "agreement", "documents", "materials"];
|
||||
|
||||
for(let i in menu)
|
||||
{
|
||||
@ -50,12 +50,17 @@ export default class InnerMenu extends React.Component
|
||||
</li>
|
||||
<li>
|
||||
<Link href={`/contract/${ number }/agreement`} shallow>
|
||||
<a className={ this.props.router && this.props.router.asPath.indexOf("agreement") > -1 ? "active" : "" }>Договор</a>
|
||||
<a className={ this.props.router && this.props.router.asPath.indexOf("agreement") > -1 ? "active" : "" }>Документы по договору</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={`/contract/${ number }/documents`} shallow>
|
||||
<a className={ this.props.router && this.props.router.asPath.indexOf("documents") > -1 ? "active" : "" }>Документы по сделке</a>
|
||||
<a className={ this.props.router && this.props.router.asPath.indexOf("documents") > -1 ? "active" : "" }>Закрывающие документы</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={`/contract/${ number }/materials`} shallow>
|
||||
<a className={ this.props.router && this.props.router.asPath.indexOf("materials") > -1 ? "active" : "" }>Документы по ФСБУ 25/2018</a>
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -16,6 +16,8 @@ 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";
|
||||
|
||||
@ -253,47 +255,68 @@ class ContractDocumentsPage extends React.Component
|
||||
|
||||
_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)
|
||||
{
|
||||
<>
|
||||
<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>
|
||||
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(' ., ') } ₽</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>
|
||||
<div className="dosc_list medium-icon">
|
||||
{ fines.slice(0, opened.indexOf('fines') > -1 ? fines.length : 3).map((fine, fine_index) => (
|
||||
<div className="row" key={ fine_index }>
|
||||
<div className="block_body" >
|
||||
<div className="transaction_detail">
|
||||
<p>№ постановления: <b>{ fine.fine_number }</b></p>
|
||||
<ul>
|
||||
<li>Сумма: <b style={{ whiteSpace: "nowrap" }}>{ numeral(fine.amount).format(' ., ') } ₽</b></li>
|
||||
<li>Дата: <b>{ moment(fine.fine_date).format("DD.MM.YYYY") }</b></li>
|
||||
<li>Статус: <b className="success">{ fine.status }</b></li>
|
||||
<li>Штраф: { fine.fine_title }</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{ opened.indexOf(type) < 0 && fines.length > 3 && (
|
||||
<div className="row" style={{ justifyContent: "center", corsor: "pointer" }} onClick={ () => this._handle_onGroup(type) }>
|
||||
<p style={{ color: "#747474" }}>Еще { fines.length - 3 } { pluralize((fines.length - 3), 'постановлений', 'постановление', 'постановления', 'постановлений') }</p>
|
||||
</div>
|
||||
) }
|
||||
|
||||
{/*}
|
||||
<DownloadPrintFormPdfButton className="download-icon" filename={ `${ number }_${ upd_document.type }_${ upd_document.num }.pdf` } contract={ number } num={ upd_document.num } date={ upd_document.date } type={ upd_document.type }/>
|
||||
{*/}
|
||||
</div>
|
||||
)) }
|
||||
</div>
|
||||
</>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
149
pages/contract/materials.js
Normal file
149
pages/contract/materials.js
Normal file
@ -0,0 +1,149 @@
|
||||
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 DownloadPdfButton from "../components/DownloadPdfButton";
|
||||
|
||||
import { getContractInfo, getContractMaterials } from "../../actions";
|
||||
|
||||
class ContractPage extends React.Component
|
||||
{
|
||||
constructor(props)
|
||||
{
|
||||
super(props);
|
||||
this.state = {
|
||||
date: null,
|
||||
car: null,
|
||||
contract_date: null,
|
||||
materials: null,
|
||||
loading: false,
|
||||
}
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState)
|
||||
{
|
||||
return {
|
||||
date: nextProps.date,
|
||||
car: nextProps.car,
|
||||
contract_date: nextProps.contract_date,
|
||||
materials: nextProps.materials,
|
||||
};
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
getContractMaterials({
|
||||
dispatch: this.props.dispatch,
|
||||
}).then(() => {
|
||||
this.setState({ loading: false })
|
||||
}).catch(() => {});
|
||||
})
|
||||
.catch(() =>
|
||||
{
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render()
|
||||
{
|
||||
const { loading, date, car, materials, } = this.state;
|
||||
const { number } = this.props;
|
||||
|
||||
console.log("materials", materials);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Head>
|
||||
<title>ЛК Эволюция автолизинга</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="ЛК Эволюция автолизинга"
|
||||
/>
|
||||
</Head>
|
||||
<Header { ...this.props }/>
|
||||
<main>
|
||||
<section>
|
||||
<div className="clear"></div>
|
||||
<div className="container">
|
||||
<div className="title_wrapper">
|
||||
<div className="left" style={{ flexDirection: 'column', }}>
|
||||
<h1 className="section_title">Договор №{ number }</h1>
|
||||
<h5 style={{ fontSize: '14px' }}>{ date !== undefined && date !== null && date !== null && (<> от { moment(date).format("DD.MM.YYYY") }</>)}{ car !== undefined && car !== null ? ` - ${ car.brand.name } ${ car.model.name } | ${ car.reg_number !== null ? car.reg_number : 'без рег. номера' } | ${ car.vin_number !== null ? car.vin_number : 'без VIN номера' }` : '' }</h5>
|
||||
</div>
|
||||
<Company/>
|
||||
</div>
|
||||
<div className="aside_container about">
|
||||
<InnerMenu number={ number } { ...this.props }/>
|
||||
<article>
|
||||
{ loading ? (
|
||||
<div className="table_row table_header" style={{ minHeight: 300, display: "flex", justifyContent: "center", alignItems: "center" }}>
|
||||
<SpinnerCircular size={90} thickness={51} speed={100} color="rgba(28, 1, 169, 1)" secondaryColor="rgba(236, 239, 244, 1)" />
|
||||
</div>
|
||||
) : (
|
||||
<div className="dosc_list">
|
||||
{ materials !== undefined && materials !== null && materials.map((document, index ) => (
|
||||
<div className="row" key={ index }>
|
||||
<p className="doc_name i-pdf">
|
||||
{ document.name }
|
||||
{ document.description !== null && document.description !== "" && (
|
||||
<span style={{ width: "100%"}}>{ document.description }</span>
|
||||
) }
|
||||
</p>
|
||||
<DownloadPdfButton url={ `${ process.env.NEXT_PUBLIC_MAIN_SITE }${ document.url }` } filename={ `${ document.filename }.pdf` } bitrix={ true }/>
|
||||
</div>
|
||||
)) }
|
||||
</div>
|
||||
) }
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<Footer/>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state, ownProps)
|
||||
{
|
||||
return {
|
||||
contract_date: state.contract.date,
|
||||
date: state.contract.date,
|
||||
car: state.contract.car,
|
||||
materials: state.contract.materials,
|
||||
}
|
||||
}
|
||||
|
||||
export const getServerSideProps = reduxWrapper.getServerSideProps(store =>
|
||||
async ({ req, res, query }) =>
|
||||
{
|
||||
return {
|
||||
props: {
|
||||
number: query.number,
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export default withRouter(connect(mapStateToProps)(ContractPage));
|
||||
@ -29,6 +29,7 @@ class LoginPage extends React.Component
|
||||
email_error: false,
|
||||
phone_form_step: 1,
|
||||
phone_number_error: false,
|
||||
phone_number_format_error: false,
|
||||
phone_code_error: false,
|
||||
email_login_disabled: true,
|
||||
phone_login_disabled: true,
|
||||
@ -158,7 +159,8 @@ class LoginPage extends React.Component
|
||||
|
||||
_handle_onPhoneChange = (value) =>
|
||||
{
|
||||
this.setState({ phone: value, phone_login_disabled: this._check_fields_disabled([ value ]), phone_number_error: false });
|
||||
const phone_number_format_error = value.length > 1 && (value[0] !== "+" || value[1] !== "7") ? true : false;
|
||||
this.setState({ phone: value, phone_login_disabled: this._check_fields_disabled([ value ]), phone_number_error: false, phone_number_format_error: phone_number_format_error });
|
||||
}
|
||||
|
||||
_handle_onPhoneCodeChange = (value) =>
|
||||
@ -166,6 +168,27 @@ class LoginPage extends React.Component
|
||||
this.setState({ phone_code: value, phone_code_submit_disabled: this._check_fields_disabled([ value ]), phone_sms_code_error: false });
|
||||
}
|
||||
|
||||
_handle_onRecover = (event) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
this.props.router.push("/recovery");
|
||||
}
|
||||
|
||||
_handle_onEmailFormFieldKey = (event) =>
|
||||
{
|
||||
const { email_login_disabled } = this.state;
|
||||
|
||||
if(event.keyCode === 13)
|
||||
{
|
||||
event.preventDefault();
|
||||
|
||||
if(!email_login_disabled)
|
||||
{
|
||||
this._handle_onEmailSubmit(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_check_fields_disabled = (values) =>
|
||||
{
|
||||
for(let i in values)
|
||||
@ -183,7 +206,7 @@ class LoginPage extends React.Component
|
||||
{
|
||||
const { email, password, phone, phone_code, tab, email_error, phone_number_error, phone_code_error,
|
||||
email_login_disabled, phone_login_disabled, phone_form_step, phone_code_submit_disabled, phone_code_resend_disabled,
|
||||
timer, phone_sms_code_error, email_auth_loading, phone_check_loading, code_check_loading } = this.state;
|
||||
timer, phone_sms_code_error, email_auth_loading, phone_check_loading, code_check_loading, phone_number_format_error } = this.state;
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
@ -211,16 +234,23 @@ class LoginPage extends React.Component
|
||||
{ tab === "email" ? (
|
||||
<form onSubmit={ this._handle_onEmailSubmit }>
|
||||
<div className="form_field">
|
||||
<input type="text" name="email" value={ email } placeholder="Введите адрес E-mail" onChange={ (event) => this._handle_onEmailChange(event.target.value) } required={ true }/>
|
||||
<input type="text" name="email" value={ email } placeholder="Введите адрес E-mail" onChange={ (event) => this._handle_onEmailChange(event.target.value) } onKeyDown={ this._handle_onEmailFormFieldKey } required={ true }/>
|
||||
</div>
|
||||
<div className="form_field">
|
||||
<input type="password" name="password" value={ password } placeholder="Введите пароль" onChange={ (event) => this._handle_onPasswordChange(event.target.value) } required={ true }/>
|
||||
<input type="password" name="password" value={ password } placeholder="Введите пароль" onChange={ (event) => this._handle_onPasswordChange(event.target.value) } onKeyDown={ this._handle_onEmailFormFieldKey } required={ true }/>
|
||||
</div>
|
||||
<div style={{ display: "flex", flexDirection: "row", justifyContent: "flex-end", alignItems: "flex-end" }}>
|
||||
<div>
|
||||
<button className="button button-blue transparent" style={{ width: "160px" }} onClick={ (event) => this._handle_onRecover(event) }>Забыли пароль?</button>
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" className="button button-blue" disabled={ email_login_disabled }>
|
||||
{ email_auth_loading ? (
|
||||
<SpinnerCircular size={24} thickness={100} speed={100} color="rgba(255, 255, 255, 1)" secondaryColor="rgba(255, 255, 255, 0.5)" style={{ marginTop: "4px" }}/>
|
||||
) : "Войти" }
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" className="button button-blue" disabled={ email_login_disabled }>
|
||||
{ email_auth_loading ? (
|
||||
<SpinnerCircular size={24} thickness={100} speed={100} color="rgba(255, 255, 255, 1)" secondaryColor="rgba(255, 255, 255, 0.5)" style={{ marginTop: "4px" }}/>
|
||||
) : "Войти" }
|
||||
</button>
|
||||
<p>{ email_error ? 'Ошибка: Неверный логин или пароль' : `\u00A0` }</p>
|
||||
</form>
|
||||
) : (
|
||||
@ -238,11 +268,12 @@ class LoginPage extends React.Component
|
||||
</button>
|
||||
</form>
|
||||
<p>{ phone_number_error ? 'Ошибка: нет аккаунта с таким номером телефона' : `\u00A0` }</p>
|
||||
<p>{ phone_number_format_error ? 'Ошибка: номер должен начинаться на +7' : `\u00A0` }</p>
|
||||
</>
|
||||
) }
|
||||
{ phone_form_step === 2 && (
|
||||
<>
|
||||
<p className="message">На номер <strong>+{ phone }</strong> отправлен код подтверждения.</p>
|
||||
<p className="message">На номер <strong>+{ phone.replace(/[^0-9.]/g, '') }</strong> отправлен код подтверждения.</p>
|
||||
<form onSubmit={ this._handle_onCodeSubmit }>
|
||||
<div className="form_field">
|
||||
<input type="text" name="phone_code" value={ phone_code } placeholder="Введите код из СМС" onChange={ (event) => this._handle_onPhoneCodeChange(event.target.value) } />
|
||||
|
||||
@ -1,102 +1,289 @@
|
||||
import React from "react";
|
||||
import Head from 'next/head';
|
||||
import Link from "next/link";
|
||||
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";
|
||||
|
||||
export default function RecoveryPassPage() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Head>
|
||||
<title>ЛК Эволюция автолизинга</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="ЛК Эволюция автолизинга"
|
||||
/>
|
||||
</Head>
|
||||
<Header />
|
||||
<main>
|
||||
<section>
|
||||
<div className="clear"></div>
|
||||
<div className="container">
|
||||
<h1 className="section_title">Восстановление пароля</h1>
|
||||
<div className="login recovery">
|
||||
<div className="login_with">
|
||||
<p>Восстановить с помощью</p>
|
||||
<div className="tabs">
|
||||
<div className="tab active">Номера телефона</div>
|
||||
<div className="tab">Электронной почты</div>
|
||||
import { sendEmailCheck, sendEmailCode, sendPassword } from "../actions/recoveryActions";
|
||||
|
||||
export default class RecoveryPage extends React.Component
|
||||
{
|
||||
constructor(props)
|
||||
{
|
||||
super(props);
|
||||
this.state = {
|
||||
email: "",
|
||||
email_code: "",
|
||||
password: "",
|
||||
password_repeat: "",
|
||||
tab: "email",
|
||||
email_error: false,
|
||||
recovery_form_step: 1,
|
||||
email_code_error: false,
|
||||
email_send_disabled: false,
|
||||
set_password_disabled: true,
|
||||
email_code_submit_disabled: true,
|
||||
email_code_resend_disabled: true,
|
||||
timer: 0,
|
||||
email_auth_loading: false,
|
||||
email_check_loading: false,
|
||||
code_check_loading: false,
|
||||
password_check_loading: false,
|
||||
password_submit_disabled: true,
|
||||
password_error: false,
|
||||
};
|
||||
|
||||
this.timer_ref = null;
|
||||
}
|
||||
|
||||
_handle_onEmailSubmit = (event) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
|
||||
const { email, email_check_loading } = this.state;
|
||||
|
||||
if(!email_check_loading)
|
||||
{
|
||||
this.setState({ email_check_loading: true }, () =>
|
||||
{
|
||||
sendEmailCheck({ email })
|
||||
.then(() =>
|
||||
{
|
||||
this.setState({ email_check_loading: false, email_error: false, timer: 60, recovery_form_step: 2, }, () =>
|
||||
{
|
||||
this.timer_ref = setInterval(() =>
|
||||
{
|
||||
const t = this.state.timer - 1;
|
||||
this.setState({ timer: t, }, () =>
|
||||
{
|
||||
if(t === 0)
|
||||
{
|
||||
clearInterval(this.timer_ref);
|
||||
}
|
||||
});
|
||||
}, 1000);
|
||||
});
|
||||
})
|
||||
.catch(() =>
|
||||
{
|
||||
this.setState({ email_error: true, email_check_loading: false });
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_handle_onCodeSubmit = (event) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
|
||||
const { email, email_code, code_check_loading } = this.state;
|
||||
|
||||
if(!code_check_loading)
|
||||
{
|
||||
this.setState({ code_check_loading: true }, () =>
|
||||
{
|
||||
sendEmailCode({ email, code: email_code })
|
||||
.then(() =>
|
||||
{
|
||||
this.setState({ email_code_error: false, code_check_loading: false, recovery_form_step: 3, });
|
||||
})
|
||||
.catch(() =>
|
||||
{
|
||||
this.setState({ email_code_error: true, code_check_loading: false });
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_handle_onPasswordSubmit = (event) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
|
||||
const { email, email_code, password, password_repeat, password_check_loading, } = this.state;
|
||||
|
||||
if(!password_check_loading)
|
||||
{
|
||||
this.setState({ password_check_loading: true }, () =>
|
||||
{
|
||||
sendPassword({ email, code: email_code, password, password_repeat, })
|
||||
.then(() =>
|
||||
{
|
||||
this.setState({ password_error: false, password_check_loading: false, recovery_form_step: 4, });
|
||||
})
|
||||
.catch(() =>
|
||||
{
|
||||
this.setState({ password_error: true, password_check_loading: false });
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_handle_onResendEmailCode = (event) =>
|
||||
{
|
||||
this.setState({ email_code_error: false }, () =>
|
||||
{
|
||||
this._handle_onEmailSubmit(event);
|
||||
});
|
||||
}
|
||||
|
||||
_handle_onEmailChange = (value) =>
|
||||
{
|
||||
this.setState({ email: value, email_send_disabled: this._check_fields_disabled([ value, this.state.email ]), email_error: false });
|
||||
}
|
||||
|
||||
_handle_onPasswordChange = (value) =>
|
||||
{
|
||||
this.setState({ password: value, set_password_disabled: this._check_fields_disabled([ value, this.state.password ]), password_error: false });
|
||||
}
|
||||
|
||||
_handle_onPasswordCheckChange = (value) =>
|
||||
{
|
||||
this.setState({ password_repeat: value, set_password_disabled: this._check_fields_disabled([ value, this.state.password_repeat ]), password_error: false });
|
||||
}
|
||||
|
||||
_handle_onEmailCodeChange = (value) =>
|
||||
{
|
||||
this.setState({ email_code: value, email_code_submit_disabled: this._check_fields_disabled([ value ]), email_code_error: false });
|
||||
}
|
||||
|
||||
_handle_onPasswordChange = (value) =>
|
||||
{
|
||||
let error = value === this.state.password_repeat ? false : true;
|
||||
error = value.length < 6 ? true : error;
|
||||
|
||||
this.setState({ password: value, password_submit_disabled: error ? true : this._check_fields_disabled([ value ]), password_error: error });
|
||||
}
|
||||
|
||||
_handle_onPasswordRepeatChange = (value) =>
|
||||
{
|
||||
let error = value === this.state.password ? false : true;
|
||||
error = value.length < 6 ? true : error;
|
||||
|
||||
this.setState({ password_repeat: value, password_submit_disabled: error ? true : this._check_fields_disabled([ value ]), password_error: error });
|
||||
}
|
||||
|
||||
_check_fields_disabled = (values) =>
|
||||
{
|
||||
for(let i in values)
|
||||
{
|
||||
if(values[i] === "")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
render()
|
||||
{
|
||||
const { email, email_code, tab, email_error, email_code_error,
|
||||
set_password_disabled, email_send_disabled, recovery_form_step, email_code_submit_disabled, email_code_resend_disabled,
|
||||
timer, email_auth_loading, email_check_loading, code_check_loading,
|
||||
password, password_repeat, password_submit_disabled, password_check_loading, password_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">
|
||||
<h1 className="section_title">Восстановление пароля</h1>
|
||||
<div className="login recovery">
|
||||
<div className="login_with">
|
||||
<p>Восстановить с помощью</p>
|
||||
<div className="tabs">
|
||||
<div className="tab active">Электронной почты</div>
|
||||
</div>
|
||||
</div>
|
||||
{ recovery_form_step === 1 && (
|
||||
<>
|
||||
<form onSubmit={ this._handle_onEmailSubmit }>
|
||||
<div className="form_field">
|
||||
<input type="text" name="email" value={ email } placeholder="Введите адрес E-mail" onChange={ (event) => this._handle_onEmailChange(event.target.value) } required={ true }/>
|
||||
</div>
|
||||
<button type="submit" className="button button-blue" disabled={ email_send_disabled }>
|
||||
{ email_auth_loading ? (
|
||||
<SpinnerCircular size={24} thickness={100} speed={100} color="rgba(255, 255, 255, 1)" secondaryColor="rgba(255, 255, 255, 0.5)" style={{ marginTop: "4px" }}/>
|
||||
) : "Получить код" }
|
||||
</button>
|
||||
</form>
|
||||
<p>{ email_error ? 'Ошибка: Неверный адрес E-mail' : `\u00A0` }</p>
|
||||
</>
|
||||
) }
|
||||
{ recovery_form_step === 2 && (
|
||||
<>
|
||||
<p className="message">На адрес E-mail <strong>{ email }</strong> отправлен код подтверждения.</p>
|
||||
<form onSubmit={ this._handle_onCodeSubmit }>
|
||||
<div className="form_field">
|
||||
<input type="text" name="email_code" value={ email_code } placeholder="Введите код из письма" onChange={ (event) => this._handle_onEmailCodeChange(event.target.value) } />
|
||||
</div>
|
||||
<button type="submit" className="button button-blue" disabled={ email_code_submit_disabled }>
|
||||
{ code_check_loading ? (
|
||||
<SpinnerCircular size={24} thickness={100} speed={100} color="rgba(255, 255, 255, 1)" secondaryColor="rgba(255, 255, 255, 0.5)" style={{ marginTop: "4px" }}/>
|
||||
) : "Отправить код" }
|
||||
</button>
|
||||
</form>
|
||||
<div className="resend" style={{ justifyContent: "flex-start" }}>
|
||||
{ timer !== 0 ? (
|
||||
<p>Запросить код повторно можно через: { timer } { pluralize(timer, 'секунд', 'секунду', 'секунды', 'секунд') }</p>
|
||||
) : (
|
||||
<button className="button button-blue transparent" onClick={ (event) => this._handle_onResendEmailCode(event) }>Запросить код повторно</button>
|
||||
) }
|
||||
{/* disabled={ email_code_resend_disabled }*/}
|
||||
</div>
|
||||
<p>{ email_code_error ? 'Ошибка: Вы указали неверный код' : `\u00A0` }</p>
|
||||
</>
|
||||
) }
|
||||
{ recovery_form_step === 3 && (
|
||||
<>
|
||||
<p className="message">Вы указали верный код. Введите новый пароль и повторите новый пароль</p>
|
||||
<form onSubmit={ this._handle_onPasswordSubmit } className="newPass_form">
|
||||
<div className="form_field">
|
||||
<input type="password" name="password" value={ password } placeholder="Введите новый пароль" onChange={ (event) => this._handle_onPasswordChange(event.target.value) } />
|
||||
</div>
|
||||
<div className="form_field">
|
||||
<input type="password" name="password_repeat" value={ password_repeat } placeholder="Повторите новый пароль" onChange={ (event) => this._handle_onPasswordRepeatChange(event.target.value) } />
|
||||
</div>
|
||||
<button type="submit" className="button button-blue" disabled={ password_submit_disabled }>
|
||||
{ password_check_loading ? (
|
||||
<SpinnerCircular size={24} thickness={100} speed={100} color="rgba(255, 255, 255, 1)" secondaryColor="rgba(255, 255, 255, 0.5)" style={{ marginTop: "4px" }}/>
|
||||
) : "Изменить пароль" }
|
||||
</button>
|
||||
</form>
|
||||
<p>{ password_error ? 'Внимание: пароли не совпадают' : `\u00A0` }</p>
|
||||
<p>{ password.length < 6 ? 'Внимание: минимальная длина пароля - 6 символов' : `\u00A0` }</p>
|
||||
</>
|
||||
) }
|
||||
{ recovery_form_step === 4 && (
|
||||
<>
|
||||
<p className="message">Поздравляем, пароль успешно изменен. <Link href="/login"><a style={{ cursor: "pointer" }}>Нажмите здесь для авторизации</a></Link>.</p>
|
||||
</>
|
||||
) }
|
||||
</div>
|
||||
<form>
|
||||
<div className="form_field">
|
||||
<input type="text" name="login" value="" placeholder="Введите номер телефона" />
|
||||
</div>
|
||||
<button type="submit" className="button button-blue" disabled>Получить код</button>
|
||||
</form>
|
||||
{/* Step 2
|
||||
<p className="message">На указанный номер отправлен код.</p>
|
||||
<form>
|
||||
<div className="form_field">
|
||||
<input type="text" name="pass" value="" placeholder="Введите код из СМС" />
|
||||
</div>
|
||||
|
||||
<button type="submit" className="button button-blue" disabled>Отправить код</button>
|
||||
</form>
|
||||
|
||||
<div className="resend">
|
||||
<p>Запросить код повторно можно через: 60 секунд</p>
|
||||
<button className="button button-blue transparent" disabled>Запросить код повторно</button>
|
||||
</div>
|
||||
*/}
|
||||
{/* Step 3 */}
|
||||
{/*<form className="newPass_form">
|
||||
<div className="form_field">
|
||||
<input type="text" name="new_pass" value="" placeholder="Введите новый пароль" />
|
||||
</div>
|
||||
<div className="form_field">
|
||||
<input type="text" name="new_pass" value="" placeholder="Повторите новый пароль" />
|
||||
</div>
|
||||
|
||||
<button type="submit" className="button button-blue" disabled>Сохранить</button>
|
||||
</form>*/}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="order">
|
||||
<div className="container wide">
|
||||
<h2 className="section_title">Купить в лизинг?</h2>
|
||||
|
||||
<div className="order_form">
|
||||
<div className="order_email">
|
||||
<p>Напишите на <a href="mailto:">buy@domain.ru</a> или заполните форму</p>
|
||||
</div>
|
||||
|
||||
<form>
|
||||
<div className="form_field">
|
||||
<input type="text" value="" placeholder="Имя" />
|
||||
</div>
|
||||
<div className="form_field">
|
||||
<input type="tel" value="" placeholder="Телефон" />
|
||||
</div>
|
||||
<div className="form_field">
|
||||
<input type="email" value="" placeholder="E-mail" />
|
||||
</div>
|
||||
<div className="form_field">
|
||||
<input type="text" value="" placeholder="Организация" />
|
||||
</div>
|
||||
<div className="policy">
|
||||
<input type="checkbox" name="policy" id="policy" hidden checked />
|
||||
<label for="policy">Даю свое согласие на обработку моих персональных данных</label>
|
||||
</div>
|
||||
<button className="button">Отправить</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<Footer />
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
</section>
|
||||
<FormRequest/>
|
||||
</main>
|
||||
<Footer />
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,114 +0,0 @@
|
||||
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 { withRouter } from 'next/router';
|
||||
import { reduxWrapper } from '../store';
|
||||
|
||||
import Header from './components/Header';
|
||||
import Footer from './components/Footer';
|
||||
import Pagination from './components/Pagination';
|
||||
|
||||
import { logout } from '../actions';
|
||||
|
||||
class IndexPage extends React.Component
|
||||
{
|
||||
constructor(props)
|
||||
{
|
||||
super(props);
|
||||
this.state = {
|
||||
};
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState)
|
||||
{
|
||||
return {
|
||||
};
|
||||
}
|
||||
|
||||
_handle_onLogout = () =>
|
||||
{
|
||||
logout({ dispatch: this.props.dispatch }).then().catch();
|
||||
}
|
||||
|
||||
render()
|
||||
{
|
||||
const { loading, page, pages, search, date_from, date_from_type, date_to, date_to_type, contracts, sort_number, sort_date, sort_status } = this.state;
|
||||
console.log("contracts");
|
||||
console.log(contracts);
|
||||
const contract_status = {
|
||||
"Действующий": "opened",
|
||||
"Закрыт": "closed",
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Head>
|
||||
<title>ЛК Эволюция автолизинга</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="ЛК Эволюция автолизинга"
|
||||
/>
|
||||
</Head>
|
||||
<Header { ...this.props }/>
|
||||
<main>
|
||||
<section>
|
||||
<div className="clear"></div>
|
||||
<div className="container">
|
||||
<h1 className="section_title">Настройки</h1>
|
||||
<button onClick={ this._handle_onLogout }>Выйти из личного кабинета</button>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<Footer/>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state, ownProps)
|
||||
{
|
||||
return {
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
66
pages/settings/components/InnerMenu/index.js
Normal file
66
pages/settings/components/InnerMenu/index.js
Normal file
@ -0,0 +1,66 @@
|
||||
import React from "react";
|
||||
import Link from "next/link";
|
||||
|
||||
const menu = [
|
||||
{id: 1, name: "Номер телефона", link: "/settings/phone"},
|
||||
{id: 2, name: "Пароль", link: "/settings/password"},
|
||||
]
|
||||
|
||||
export default class InnerMenu extends React.Component
|
||||
{
|
||||
constructor(props)
|
||||
{
|
||||
super(props);
|
||||
this.menuRef = React.createRef();
|
||||
|
||||
menu.forEach(item =>
|
||||
{
|
||||
this[item.id] = React.createRef();
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount()
|
||||
{
|
||||
let l = 0;
|
||||
let m = 0;
|
||||
|
||||
for(let i in menu)
|
||||
{
|
||||
if(this.props.router.asPath.indexOf(menu[i].link) > -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;
|
||||
}
|
||||
|
||||
scrollToCategory = id => {
|
||||
|
||||
};
|
||||
|
||||
render()
|
||||
{
|
||||
return (
|
||||
<aside>
|
||||
<ul className="aside_nav" ref={ this.menuRef }>
|
||||
{ menu.map(item => (
|
||||
<li key = {item.id} ref={this[item.id]} onClick={() => this.scrollToCategory(item.id)}>
|
||||
<Link
|
||||
href={item.link}
|
||||
shallow
|
||||
>
|
||||
<a className={ this.props.router && this.props.router.route === item.link ? "active" : "" }>{item.name}</a>
|
||||
</Link>
|
||||
</li>
|
||||
)) }
|
||||
</ul>
|
||||
</aside>
|
||||
)
|
||||
}
|
||||
}
|
||||
231
pages/settings/password.js
Normal file
231
pages/settings/password.js
Normal file
@ -0,0 +1,231 @@
|
||||
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 { 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 { sendNewPassword } from '../../actions';
|
||||
|
||||
class IndexPage extends React.Component
|
||||
{
|
||||
constructor(props)
|
||||
{
|
||||
super(props);
|
||||
this.state = {
|
||||
password_form_step: 1,
|
||||
password: "",
|
||||
password_error: false,
|
||||
new_password: "",
|
||||
new_password_repeat: "",
|
||||
new_password_check_loading: false,
|
||||
new_password_submit_disabled: true,
|
||||
new_password_error: false,
|
||||
user: {},
|
||||
};
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState)
|
||||
{
|
||||
return {
|
||||
user: nextProps.user,
|
||||
};
|
||||
}
|
||||
|
||||
_handle_onPasswordSubmit = (event) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
|
||||
const { password, new_password, new_password_repeat, new_password_check_loading, user, } = this.state;
|
||||
|
||||
if(!new_password_check_loading)
|
||||
{
|
||||
this.setState({ new_password_check_loading: true }, () =>
|
||||
{
|
||||
sendNewPassword({ email: user.email, password, new_password, new_password_repeat, })
|
||||
.then((response) =>
|
||||
{
|
||||
if(response.status === "success")
|
||||
{
|
||||
this.setState({ new_password_error: false, new_password_check_loading: false, password_form_step: 2, });
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log(response.error);
|
||||
if(response.status === "error" && response.error === "wrong_email")
|
||||
{
|
||||
this.setState({ password_error: true, new_password_error: false, new_password_check_loading: false });
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() =>
|
||||
{
|
||||
this.setState({ new_password_error: true, new_password_check_loading: false });
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_handle_onPasswordChange = (value) =>
|
||||
{
|
||||
this.setState({ password: value, password_error: false, new_password_submit_disabled: this._check_fields_disabled([ value, this.state.new_password, this.state.new_password_repeat ]), });
|
||||
}
|
||||
|
||||
_handle_onNewPasswordChange = (value) =>
|
||||
{
|
||||
let error = false;
|
||||
if(this.state.new_password_repeat.length > 0)
|
||||
{
|
||||
value === this.state.new_password ? false : true;
|
||||
error = value.length < 6 ? true : error;
|
||||
}
|
||||
|
||||
this.setState({ new_password: value, new_password_submit_disabled: this._check_fields_disabled([ value, this.state.password, this.state.new_password_repeat ]), new_password_error: false });
|
||||
}
|
||||
|
||||
_handle_onNewPasswordRepeatChange = (value) =>
|
||||
{
|
||||
let error = value === this.state.new_password ? false : true;
|
||||
error = value.length < 6 ? true : error;
|
||||
|
||||
this.setState({ new_password_repeat: value, new_password_submit_disabled: error ? true : this._check_fields_disabled([ value, this.state.password, this.state.new_password ]), new_password_error: error });
|
||||
}
|
||||
|
||||
_check_fields_disabled = (values) =>
|
||||
{
|
||||
for(let i in values)
|
||||
{
|
||||
if(values[i] === "")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
render()
|
||||
{
|
||||
console.log("this.state.user", this.state.user);
|
||||
const { password, password_error, new_password, new_password_repeat, new_password_submit_disabled, new_password_check_loading, new_password_error, password_form_step } = 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">
|
||||
<h1 className="section_title">Смена пароля</h1>
|
||||
</div>
|
||||
<Company/>
|
||||
</div>
|
||||
<div className="aside_container about">
|
||||
<InnerMenu { ...this.props }/>
|
||||
<article>
|
||||
{ password_form_step === 1 && (
|
||||
<div className={`login recovery`}>
|
||||
<form onSubmit={ this._handle_onPasswordSubmit } className="newPass_form">
|
||||
<p className="message">Введите Ваш текущий пароль</p>
|
||||
<div className="form_field">
|
||||
<input type="password" name="password" value={ password } placeholder="Текущий пароль" onChange={ (event) => this._handle_onPasswordChange(event.target.value) } />
|
||||
</div>
|
||||
<p style={{ width: "100%" }}>{ password_error ? 'Ошибка: неверный пароль' : `\u00A0` }</p>
|
||||
<p style={{ width: "100%" }} className="message"><br/></p>
|
||||
<p style={{ width: "100%" }} className="message"><br/></p>
|
||||
<p className="message">Введите новый пароль и повторите новый пароль</p>
|
||||
<div className="form_field">
|
||||
<input type="password" name="new_password" value={ new_password } placeholder="Новый пароль" onChange={ (event) => this._handle_onNewPasswordChange(event.target.value) } />
|
||||
</div>
|
||||
<div className="form_field">
|
||||
<input type="password" name="new_password_repeat" value={ new_password_repeat } placeholder="Новый пароль (повторите)" onChange={ (event) => this._handle_onNewPasswordRepeatChange(event.target.value) } />
|
||||
</div>
|
||||
<button type="submit" className="button button-blue" disabled={ new_password_submit_disabled }>
|
||||
{ new_password_check_loading ? (
|
||||
<SpinnerCircular size={24} thickness={100} speed={100} color="rgba(255, 255, 255, 1)" secondaryColor="rgba(255, 255, 255, 0.5)" style={{ marginTop: "4px" }}/>
|
||||
) : "Изменить пароль" }
|
||||
</button>
|
||||
</form>
|
||||
<p>{ new_password_error ? 'Внимание: пароли не совпадают' : `\u00A0` }</p>
|
||||
<p>{ new_password.length < 6 ? 'Внимание: минимальная длина пароля - 6 символов' : `\u00A0` }</p>
|
||||
</div>
|
||||
) }
|
||||
{ password_form_step === 2 && (
|
||||
<div className={`login recovery`}>
|
||||
<p className="message">Ваш пароль был успешно изменен.</p>
|
||||
</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));
|
||||
285
pages/settings/phone.js
Normal file
285
pages/settings/phone.js
Normal file
@ -0,0 +1,285 @@
|
||||
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 = {
|
||||
phone: "",
|
||||
phone_code: "",
|
||||
phone_form_step: 1,
|
||||
phone_number_error: false,
|
||||
phone_number_format_error: false,
|
||||
phone_code_error: false,
|
||||
phone_login_disabled: true,
|
||||
phone_code_submit_disabled: true,
|
||||
phone_code_resend_disabled: true,
|
||||
phone_sms_code_error: false,
|
||||
timer: 0,
|
||||
phone_check_loading: false,
|
||||
code_check_loading: false,
|
||||
user: {},
|
||||
};
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState)
|
||||
{
|
||||
return {
|
||||
user: nextProps.user,
|
||||
};
|
||||
}
|
||||
|
||||
_handle_onPhoneSubmit = (event) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
|
||||
const { user, phone, phone_check_loading } = this.state;
|
||||
|
||||
if(!phone_check_loading)
|
||||
{
|
||||
this.setState({ phone_check_loading: true }, () =>
|
||||
{
|
||||
sendPhoneChangeNumber({ email: user.email, phone })
|
||||
.then(() =>
|
||||
{
|
||||
this.setState({ phone_check_loading: false, phone_number_error: false, timer: 60, phone_form_step: 2, }, () =>
|
||||
{
|
||||
this.timer_ref = setInterval(() =>
|
||||
{
|
||||
const t = this.state.timer - 1;
|
||||
this.setState({ timer: t, }, () =>
|
||||
{
|
||||
if(t === 0)
|
||||
{
|
||||
clearInterval(this.timer_ref);
|
||||
}
|
||||
});
|
||||
}, 1000);
|
||||
});
|
||||
})
|
||||
.catch(() =>
|
||||
{
|
||||
this.setState({ phone_number_error: true, phone_check_loading: false });
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_handle_onCodeSubmit = (event) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
|
||||
const { phone, phone_code, code_check_loading } = this.state;
|
||||
|
||||
if(!code_check_loading)
|
||||
{
|
||||
this.setState({ code_check_loading: true }, () =>
|
||||
{
|
||||
sendPhoneChangeNumberSmsCode({ phone, code: phone_code })
|
||||
.then(() =>
|
||||
{
|
||||
const new_user = { ...this.state.user };
|
||||
new_user.phone = phone;
|
||||
|
||||
setUserPhone({ dispatch: this.props.dispatch, user: new_user });
|
||||
|
||||
this.setState({ phone_sms_code_error: false, code_check_loading: false, phone_form_step: 3 });
|
||||
})
|
||||
.catch(() =>
|
||||
{
|
||||
this.setState({ phone_sms_code_error: true, code_check_loading: false });
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_handle_onResendCode = (event) =>
|
||||
{
|
||||
this.setState({ phone_sms_code_error: false }, () =>
|
||||
{
|
||||
this._handle_onPhoneSubmit(event);
|
||||
});
|
||||
}
|
||||
|
||||
_handle_onPhoneChange = (value) =>
|
||||
{
|
||||
const phone_number_format_error = value.length > 1 && (value[0] !== "+" || value[1] !== "7") ? true : false;
|
||||
this.setState({ phone: value, phone_login_disabled: this._check_fields_disabled([ value ]), phone_number_error: false, phone_number_format_error: phone_number_format_error });
|
||||
}
|
||||
|
||||
_handle_onPhoneCodeChange = (value) =>
|
||||
{
|
||||
this.setState({ phone_code: value, phone_code_submit_disabled: this._check_fields_disabled([ value ]), phone_sms_code_error: false });
|
||||
}
|
||||
|
||||
_check_fields_disabled = (values) =>
|
||||
{
|
||||
for(let i in values)
|
||||
{
|
||||
if(values[i] === "")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
render()
|
||||
{
|
||||
const { user, phone, phone_code, phone_number_error, phone_code_error,
|
||||
phone_login_disabled, phone_form_step, phone_code_submit_disabled, phone_code_resend_disabled,
|
||||
timer, phone_sms_code_error, phone_check_loading, code_check_loading, phone_number_format_error } = 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">
|
||||
<h1 className="section_title">Вход по номеру телефона</h1>
|
||||
</div>
|
||||
<Company/>
|
||||
</div>
|
||||
<div className="aside_container about">
|
||||
<InnerMenu { ...this.props }/>
|
||||
<article>
|
||||
{ phone_form_step !== 2 && phone_form_step !== 3 && (
|
||||
<>
|
||||
{ user.phone !== undefined && user.phone !== null && user.phone !== "" ? (
|
||||
<p>Номер для авторизации <strong>+{ user.phone.replace(/[^0-9.]/g, '') }</strong>. Вы можете изменить номер телефона для авторизации.</p>
|
||||
) : (
|
||||
<p>У Вас отсутствует привязанный номер телефона. Вы можете добавить номер телефона для авторизации.</p>
|
||||
) }
|
||||
</>
|
||||
) }
|
||||
<p><br/></p>
|
||||
<div className={`login recovery`}>
|
||||
{ phone_form_step === 1 && (
|
||||
<>
|
||||
<form onSubmit={ this._handle_onPhoneSubmit }>
|
||||
<div className="form_field">
|
||||
<input type="text" name="phone" value={ phone } placeholder="Введите номер телефона, например +7 900 111 22 33" onChange={ (event) => this._handle_onPhoneChange(event.target.value) } required={ true }/>
|
||||
</div>
|
||||
<button type="submit" className="button button-blue" disabled={ phone_login_disabled }>
|
||||
{ phone_check_loading ? (
|
||||
<SpinnerCircular size={24} thickness={100} speed={100} color="rgba(255, 255, 255, 1)" secondaryColor="rgba(255, 255, 255, 0.5)" style={{ marginTop: "4px" }}/>
|
||||
) : "Получить код" }
|
||||
</button>
|
||||
</form>
|
||||
<p>{ phone_number_error ? 'Ошибка: нет аккаунта с таким номером телефона' : `\u00A0` }</p>
|
||||
<p>{ phone_number_format_error ? 'Ошибка: номер должен начинаться на +7' : `\u00A0` }</p>
|
||||
</>
|
||||
) }
|
||||
{ phone_form_step === 2 && (
|
||||
<>
|
||||
<p className="message">На номер <strong>+{ phone.replace(/[^0-9.]/g, '') }</strong> отправлен код подтверждения.</p>
|
||||
<form onSubmit={ this._handle_onCodeSubmit }>
|
||||
<div className="form_field">
|
||||
<input type="text" name="phone_code" value={ phone_code } placeholder="Введите код из СМС" onChange={ (event) => this._handle_onPhoneCodeChange(event.target.value) } />
|
||||
</div>
|
||||
<button type="submit" className="button button-blue" disabled={ phone_code_submit_disabled }>
|
||||
{ code_check_loading ? (
|
||||
<SpinnerCircular size={24} thickness={100} speed={100} color="rgba(255, 255, 255, 1)" secondaryColor="rgba(255, 255, 255, 0.5)" style={{ marginTop: "4px" }}/>
|
||||
) : "Отправить код" }
|
||||
</button>
|
||||
</form>
|
||||
<div className="resend" style={{ justifyContent: "flex-start" }}>
|
||||
{ timer !== 0 ? (
|
||||
<p>Запросить код повторно можно через: { timer } { pluralize(timer, 'секунд', 'секунду', 'секунды', 'секунд') }</p>
|
||||
) : (
|
||||
<button className="button button-blue transparent" onClick={ (event) => this._handle_onResendCode(event) }>Запросить код повторно</button>
|
||||
) }
|
||||
{/* disabled={ phone_code_resend_disabled }*/}
|
||||
</div>
|
||||
<p>{ phone_sms_code_error ? 'Ошибка: Вы указали неверный код' : `\u00A0` }</p>
|
||||
</>
|
||||
) }
|
||||
{ phone_form_step === 3 && (
|
||||
<p className="message">Вы успешно привязали номер <strong>+{ phone.replace(/[^0-9.]/g, '') }</strong> к Вашей учетной записи.</p>
|
||||
) }
|
||||
</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));
|
||||
@ -97,6 +97,14 @@ const contractReducer = (state = initialState.contract, action) =>
|
||||
};
|
||||
}
|
||||
|
||||
case actionTypes.CONTRACT_MATERIALS:
|
||||
{
|
||||
return {
|
||||
...state,
|
||||
materials: action.data.materials,
|
||||
};
|
||||
}
|
||||
|
||||
default: {
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@ export const defaultState = {
|
||||
agreement: null,
|
||||
documents: null,
|
||||
rules: null,
|
||||
materials: null,
|
||||
},
|
||||
calendar: {
|
||||
payments: null,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user