update for API reads

This commit is contained in:
merelendor 2023-04-04 14:52:31 +03:00
parent 658280896c
commit 0bca5b0e30
24 changed files with 922 additions and 236 deletions

View File

@ -7,6 +7,7 @@ import fileDownload from 'js-file-download';
import { eachSeries, each } from "async";
import * as actionTypes from '../constants/actionTypes';
import { getCitizenshipTitleByCode } from '../utils/citizenship';
if(process.browser)
{
@ -24,36 +25,60 @@ if(process.browser)
};
}
export const getQuestionnaire = ({ dispatch }) =>
export const getQuestionnaire = ({ dispatch, id }) =>
{
console.log("ACTION", "support", "getAppeals()", `${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/questionnaire/get`);
return new Promise((resolve, reject) =>
{
axios.get(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/questionnaire/get`)
axios.get(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/questionnaire/get`, {
params: {
id
}
})
.then((response) =>
{
console.log("ACTION", "questionnaire", "getQuestionnaire()", "response", response.data);
const questionnaire = JSON.parse(JSON.stringify(global.store.getState().questionnaire));
questionnaire.main.title = response.data.title;
questionnaire.main.inn = response.data.inn;
questionnaire.main.kpp = response.data.kpp;
questionnaire.main.telephone = response.data.telephone;
questionnaire.main.email = response.data.email;
questionnaire.main.websiteurl = response.data.websiteurl !== null ? response.data.websiteurl : "";
questionnaire.main.financial_loan = response.data.financial_loan !== null ? response.data.financial_loan : "";
if(questionnaire.status === "empty")
{
questionnaire.main.title = response.data.title;
questionnaire.main.inn = response.data.inn;
questionnaire.main.kpp = response.data.kpp;
questionnaire.main.telephone = response.data.telephone;
questionnaire.main.email = response.data.email;
questionnaire.main.websiteurl = response.data.websiteurl !== null ? response.data.websiteurl : "";
questionnaire.main.financial_loan = response.data.financial_loan !== null ? response.data.financial_loan : "";
questionnaire.contacts.fact_address = response.data.fact_address;
questionnaire.contacts.postal_address = response.data.postal_address;
questionnaire.contacts.legal_address = response.data.legal_address;
questionnaire.contacts.address_type = response.data.inn.length > 10 ? "fact" : "legal";
questionnaire.contacts.fact_address = response.data.fact_address;
questionnaire.contacts.postal_address = response.data.postal_address;
questionnaire.contacts.legal_address = response.data.legal_address;
console.log("questionnairequestionnairequestionnaire FROM JSON", questionnaire);
updateQuestionnaire({ dispatch, questionnaire })
.then(() => {})
.catch(() => {});
//dispatch({ type: actionTypes.SUPPORT_APPEALS, data: { appeals: { list: response.data.appeals, new: response.data.new, } } });
resolve();
questionnaire.head_person = { ...questionnaire.head_person, ...response.data.head_person };
questionnaire.head_person.identity_document.citizenship = {
title: getCitizenshipTitleByCode(response.data.head_person.identity_document.citizenship_code),
code: response.data.head_person.identity_document.citizenship_code,
};
questionnaire.signatory_person = { ...questionnaire.signatory_person, ...response.data.signatory_person };
questionnaire.signatory_person.identity_document.citizenship = {
title: getCitizenshipTitleByCode(response.data.signatory_person.identity_document.citizenship_code),
code: response.data.signatory_person.identity_document.citizenship_code,
};
console.log("questionnairequestionnairequestionnaire FROM JSON", questionnaire);
updateQuestionnaire({ dispatch, questionnaire })
.then(() => {})
.catch(() => {});
//dispatch({ type: actionTypes.SUPPORT_APPEALS, data: { appeals: { list: response.data.appeals, new: response.data.new, } } });
resolve();
}
else
{
resolve();
}
})
.catch((error) =>
{
@ -93,7 +118,7 @@ export const uploadAttachmentFile = (file) =>
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/questionnaire/file/upload`, data,
{
headers: {
"Content-Type": "multipart/form-data",
"Content-Type": "multipart/form-data; charset=utf-8",
},
withCredentials: true,
})
@ -110,6 +135,32 @@ export const uploadAttachmentFile = (file) =>
});
}
export const removeAttachmentFile = (id) =>
{
console.log("ACTION", "questionnaireActions", "removeAttachmentFile()", { id });
return new Promise((resolve, reject) =>
{
axios.delete(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/questionnaire/file/remove`,
{
params: {
id
},
withCredentials: true,
})
.then(async (response) =>
{
console.log("questionnaireActions", "removeAttachmentFile()", "complete");
resolve();
})
.catch((error) =>
{
console.error(error);
reject();
});
});
}
export const downloadQuestionnaire = (download = true) =>
{
console.log("ACTION", "questionnaireActions", "downloadQuestionnaire()", );

View File

@ -36,6 +36,48 @@ export const getAddress = (query) =>
console.log("error");
console.error(error);
reject();
});
});
}
export const getFullnamePart = (query, parts) =>
{
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/suggests/name`, { query, parts }, {
withCredentials: true,
})
.then((response) =>
{
resolve(response.data);
})
.catch((error) =>
{
console.log("error");
console.error(error);
reject();
});
});
}
export const getSuggests = (type, payload) =>
{
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/suggests/${ type }`, payload, {
withCredentials: true,
})
.then((response) =>
{
resolve(response.data);
})
.catch((error) =>
{
console.log("error");
console.error(error);
reject();
});
});

View File

@ -11,11 +11,11 @@ import AsyncSelect from 'react-select/async';
import debounce from 'debounce-promise';
import { set as _set, get as _get } from 'lodash';
import { getAddress } from '../../actions';
import { getAddress, getSuggests } from '../../actions';
const suggestsAddressDebounce = (text) =>
const suggestsAddressDebounce = (query) =>
{
return getAddress(text);
return getSuggests("address", { query });
}
const suggestsAddress = debounce(suggestsAddressDebounce, 200);
@ -118,55 +118,35 @@ export default class AddressSuggests extends React.Component
render()
{
const { focused, options } = this.state;
const { value, disabled, required } = this.props;
const { value, disabled, required, placeholder } = this.props;
return (
<div className="autocomlete" style={{ position: "relative" }}>
<input type="text"
autoComplete="off"
style={{ width: "100%" }}
className={ `react-select__control react-select__control--is-focused ${ focused ? "react-select__control--menu-is-open" : "" }` }
id="address"
name="address"
value={ value }
placeholder="Введите адрес"
onChange={ (event) => this._handle_onChange(event.target.value) }
onFocus={ this._handle_onFocus }
onBlur={ this._handle_onBlur }
required={ required }
disabled={ disabled }
/>
{ focused && options.length > 0 && (
<div className="react-select__menu" style={{ position: "absolute", zIndex: 1, background: "#fff", width: "100%", left: "0px", top: "40px" }}>
<div className="react-select__menu-list">
{ options.map((option, index) =>
(
<div className="react-select__option" aria-disabled="false" tab-index="-1" key={ index } onClick={ () => this._handle_onSelect(option.value) }>{ option.value }</div>
)) }
</div>
<div className="autocomlete" style={{ position: "relative" }}>
<input type="text"
autoComplete="off"
style={{ width: "100%" }}
className={ `react-select__control react-select__control--is-focused ${ focused ? "react-select__control--menu-is-open" : "" }` }
id="address"
name="address"
value={ value }
placeholder={ placeholder !== undefined ? placeholder : "Введите адрес" }
onChange={ (event) => this._handle_onChange(event.target.value) }
onFocus={ this._handle_onFocus }
onBlur={ this._handle_onBlur }
required={ required }
disabled={ disabled }
/>
{ focused && options.length > 0 && (
<div className="react-select__menu" style={{ position: "absolute", zIndex: 1, background: "#fff", width: "100%", left: "0px", top: "40px" }}>
<div className="react-select__menu-list">
{ options.map((option, index) =>
(
<div className="react-select__option" aria-disabled="false" tab-index="-1" key={ index } onClick={ () => this._handle_onSelect(option.value) }>{ option.value }</div>
)) }
</div>
) }
</div>
);
/*
<AsyncSelect
//value={ value }
defaultInputValue={ value }
placeholder="Укажите адрес"
className="autocomlete"
classNamePrefix="react-select"
cacheOptions={ true }
defaultOptions={ this.state.options }
noOptionsMessage={ () => null }
loadingMessage={ () => null }
loadOptions={ (text) => this._getAddress(text) }
onChange={ this._handle_onChange }
//onBlur={ this._handle_onBlur }
onInputChange={ this._handle_onInputChange }
//isDisabled={ disabled ? true : false }
/>
*/
</div>
) }
</div>
);
}
}

View File

@ -0,0 +1,189 @@
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 AsyncSelect from 'react-select/async';
import debounce from 'debounce-promise';
import { set as _set, get as _get } from 'lodash';
import { getSuggests } from '../../actions';
const suggestsAddressDebounce = (query) =>
{
return getSuggests("address", { query });
}
const suggestsFirstnameDebounce = (query) =>
{
return getSuggests("name", { query, parts: ["NAME"] });
}
const suggestsMiddlenameDebounce = (query) =>
{
return getSuggests("name", { query, parts: ["PATRONYMIC"] });
}
const suggestsLastnameDebounce = (query) =>
{
return getSuggests("name", { query, parts: ["SURNAME"] });
}
const suggestsAddress = debounce(suggestsAddressDebounce, 200);
const suggestsFirstname = debounce(suggestsFirstnameDebounce, 200);
const suggestsMiddlename = debounce(suggestsMiddlenameDebounce, 200);
const suggestsLastname = debounce(suggestsLastnameDebounce, 200);
export default class SuggestsInput extends React.Component
{
constructor(props)
{
super(props);
this.state = {
focused: false,
options: [],
};
}
componentDidMount()
{
}
componentDidUpdate(prevProps, prevState)
{
}
_handle_onChange = (value) =>
{
const { focused } = this.state;
const { onChange } = this.props;
onChange(value);
if(focused)
{
this._getValue(value);
}
}
_handle_onSelect = (value) =>
{
const { onChange } = this.props;
this.setState({ focused: false }, () =>
{
onChange(value);
});
}
_handle_onFocus = () =>
{
this.setState({ focused: true });
}
_handle_onBlur = () =>
{
setTimeout(() =>
{
this.setState({ focused: false });
}, 100);
}
_getSuggests = (text) =>
{
const { type } = this.props;
return new Promise((resolve, reject) =>
{
if(type === "lastname")
{
suggestsLastname(text).then((result) => { resolve(result); }).catch(() => {});
}
if(type === "firstname")
{
suggestsFirstname(text).then((result) => { resolve(result); }).catch(() => {});
}
if(type === "middlename")
{
suggestsMiddlename(text).then((result) => { resolve(result); }).catch(() => {});
}
});
}
_getValue = (text) =>
{
return new Promise((resolve, reject) =>
{
if(text === "")
{
this.setState({ options: [], value: "" }, () =>
{
resolve([]);
});
}
else
{
this._getSuggests(text)
.then((result) =>
{
const options = [];
for(let i in result.suggestions)
{
const s = result.suggestions[i];
options.push({ value: s.value, label: s.value });
}
this.setState({ options }, () =>
{
resolve(options);
});
})
.catch(() =>
{
});
}
})
}
render()
{
const { focused, options } = this.state;
const { value, disabled, required, placeholder, name } = this.props;
return (
<div className="autocomlete" style={{ position: "relative" }}>
<input type="text"
autoComplete="off"
style={{ width: "100%" }}
className={ `react-select__control react-select__control--is-focused ${ focused ? "react-select__control--menu-is-open" : "" }` }
id={ name }
name={ name }
value={ value }
placeholder={ placeholder !== undefined ? placeholder : "Заполните поле" }
onChange={ (event) => this._handle_onChange(event.target.value) }
onFocus={ this._handle_onFocus }
onBlur={ this._handle_onBlur }
required={ required }
disabled={ disabled }
/>
{ focused && options.length > 0 && (
<div className="react-select__menu" style={{ position: "absolute", zIndex: 1, background: "#fff", width: "100%", left: "0px", top: "40px" }}>
<div className="react-select__menu-list">
{ options.map((option, index) =>
(
<div className="react-select__option" aria-disabled="false" tab-index="-1" key={ index } onClick={ () => this._handle_onSelect(option.value) }>{ option.value }</div>
)) }
</div>
</div>
) }
</div>
);
}
}

View File

@ -7,14 +7,14 @@ import { connect } from "react-redux";
import numeral from "numeral";
import pluralize from 'pluralize-ru';
import { SpinnerCircular } from 'spinners-react';
import { getAddress } from '../../../actions';
import { getSuggests } from '../../../actions';
import debounce from 'debounce-promise';
import { set as _set, get as _get } from 'lodash';
import AsyncSelect from 'react-select/async';
const suggestsAddressDebounce = (text) =>
const suggestsAddressDebounce = (query) =>
{
return getAddress(text);
return getSuggests("address", { query });
}
const suggestsAddress = debounce(suggestsAddressDebounce, 200);
@ -222,31 +222,5 @@ export default class AddressSuggestsSelect extends React.Component
/>
)
}
/*
if(value_selected !== "")
{
console.log("22222222222222222");
return (
<AsyncSelect
//defaultInputValue={ value }
placeholder="Укажите адрес"
className="autocomlete"
classNamePrefix="react-select"
cacheOptions={ true }
defaultOptions={ this.state.options }
noOptionsMessage={ () => null }
loadingMessage={ () => null }
loadOptions={ (text) => this._getAddress(text) }
onChange={ this._handle_onChange }
//onBlur={ this._handle_onBlur }
onInputChange={ this._handle_onInputChange }
/>
)
}
else
{
*/
//}
}
}

View File

@ -10,7 +10,7 @@ import { SpinnerCircular } from 'spinners-react';
import Dropzone from 'react-dropzone';
import { each, concat, concatSeries } from 'async';
import { uploadAttachmentFile } from "../../../actions";
import { uploadAttachmentFile, removeAttachmentFile } from "../../../actions";
export default class FilesList extends React.Component
{
@ -51,10 +51,20 @@ export default class FilesList extends React.Component
});
}
_handle_onRemoveFile = (file_name) =>
_handle_onRemoveFile = (file) =>
{
console.log("_handle_onRemoveFile", { file: file });
const { name, onRemoveFile } = this.props;
onRemoveFile(name, file_name);
removeAttachmentFile(file.id)
.then(() =>
{
onRemoveFile(name, file.id);
})
.catch(() =>
{
});
}
_renderFileName = (name) =>
@ -100,7 +110,7 @@ export default class FilesList extends React.Component
<p className="doc_name extension" data-format={ this._renderFileType(file) } style={{ wordBreak: "break-all", lineHeight: "15px" }}>{ this._renderFileName(file.name) }{/*}<span style={{width: "100%"}}>Постановление</span>{*/}</p>
</div>
{ !checking && (
<div style={{ position: "absolute", top: "5px", right: "5px", width: "20px", height: "20px", background: "#edeff5", flex: 1, justifyContent: "center", display: "flex", alignItems: "center", borderRadius: "10px", cursor: "pointer" }} onClick={ () => this._handle_onRemoveFile(file.name) }>
<div style={{ position: "absolute", top: "5px", right: "5px", width: "20px", height: "20px", background: "#edeff5", flex: 1, justifyContent: "center", display: "flex", alignItems: "center", borderRadius: "10px", cursor: "pointer" }} onClick={ () => this._handle_onRemoveFile(file) }>
<span style={{ color: "#919399", fontSize: "12px" }}></span>
</div>
) }
@ -121,7 +131,7 @@ export default class FilesList extends React.Component
{ !checking && (
<Dropzone onDrop={ (acceptedFiles) => this._handle_onAddFile(acceptedFiles) }>
{ ({getRootProps, getInputProps}) => (
<div className="file_upload dropzone" { ...getRootProps() } style={{ width: "32%", height: "100px", marginBottom: "25px", marginTop: "0px", }}>
<div className="file_upload dropzone" { ...getRootProps() } style={{ width: "32%", height: "100px", marginBottom: "25px", marginTop: "0px", cursor: "pointer", }}>
<div className="files"></div>
<div>
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
@ -130,9 +140,9 @@ export default class FilesList extends React.Component
<path d="M14.625 21.375H21.375" stroke="#1C01A9" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M18 18V24.75" stroke="#1C01A9" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
<label htmlFor="" className="blue unselectable" style={{ lineHeight: "12px", paddingLeft: "5px", paddingRight: "9px" }}>{ title !== undefined ? title : "Прикрепить скан документов" }</label>
<label htmlFor="" className="blue unselectable" style={{ lineHeight: "12px", paddingLeft: "5px", paddingRight: "9px", cursor: "pointer", }}>{ title !== undefined ? title : "Прикрепить скан документов" }</label>
</div>
<input type="file" />
<input { ...getInputProps() } />
</div>
) }
</Dropzone>

View File

@ -244,33 +244,35 @@ class Form_1_Main extends QuestionnaireForm
<p>сумма текущих ежемесячных платежей по действующим кредитам/договорам лизинга</p>
</div>
<div className="form_field">
<label><b>Организация является НКО</b></label>
<div>
<div className="form_field checkbox">
<input type="radio"
checked={ !main.nko }
hidden=""
id="main.nko_0"
name="main.nko"
onChange={ (event) => this._handle_onNonProfitChange() }
disabled={ main.nko && checking }
/>
<label htmlFor="main.nko_0" className="unselectable">Нет</label>
</div>
<div className="form_field checkbox">
<input type="radio"
checked={ main.nko }
hidden=""
id="main.nko_1"
name="main.nko"
onChange={ (event) => this._handle_onNonProfitChange() }
disabled={ !main.nko && checking }
/>
<label htmlFor="main.nko_1" className="unselectable">Да</label>
{ company.inn.length < 11 && (
<div className="form_field">
<label><b>Организация является НКО</b></label>
<div>
<div className="form_field checkbox">
<input type="radio"
checked={ !main.nko }
hidden=""
id="main.nko_0"
name="main.nko"
onChange={ (event) => this._handle_onNonProfitChange() }
disabled={ main.nko && checking }
/>
<label htmlFor="main.nko_0" className="unselectable">Нет</label>
</div>
<div className="form_field checkbox">
<input type="radio"
checked={ main.nko }
hidden=""
id="main.nko_1"
name="main.nko"
onChange={ (event) => this._handle_onNonProfitChange() }
disabled={ !main.nko && checking }
/>
<label htmlFor="main.nko_1" className="unselectable">Да</label>
</div>
</div>
</div>
</div>
) }
{ !checking && (
<div className="action">

View File

@ -25,20 +25,20 @@ class Form_2_Contacts extends QuestionnaireForm
loading: false,
fact_address: {
title: "",
name: "",
fias_id: "",
},
legal_address: {
title: "",
name: "",
fias_id: "",
},
postal_address: {
title: "",
name: "",
fias_id: "",
},
},
value: {
title: "",
name: "",
fias_id: "",
}
};
@ -53,6 +53,15 @@ class Form_2_Contacts extends QuestionnaireForm
componentDidMount()
{
const { company } = this.props;
const { address_type } = this.state.contacts;
console.log("company.inncompany.inncompany.inncompany.inn", company.inn, address_type);
if(company.inn.length > 10 && address_type === "legal")
{
console.log("THIS ?");
this.setState({ address_type: "fact" });
}
}
_handle_onFormSubmit = (event) =>
@ -74,7 +83,7 @@ class Form_2_Contacts extends QuestionnaireForm
if(contacts.address_type === "fact")
{
if(contacts.fact_address.title === "")
if(contacts.fact_address.name === "")
{
return true;
}
@ -82,7 +91,7 @@ class Form_2_Contacts extends QuestionnaireForm
if(contacts.address_type === "postal")
{
if(contacts.postal_address.title === "")
if(contacts.postal_address.name === "")
{
return true;
}
@ -105,7 +114,7 @@ class Form_2_Contacts extends QuestionnaireForm
<div className="form_field">
<label>Фактический адрес</label>
<AddressSuggests
value={ fact_address.title }
value={ fact_address.name }
fias={ fact_address.fias_id }
onChange={ (data) => this._handle_onTextFieldChange("contacts.fact_address", data) }
required={ address_type === "fact" ? true : false }
@ -157,7 +166,7 @@ class Form_2_Contacts extends QuestionnaireForm
<label htmlFor="contacts.address_type_postal" className="unselectable" style={{ width: "100%" }}>
<span>По следующему адресу</span>
<AddressSuggests
value={ postal_address.title }
value={ postal_address.name }
fias={ postal_address.fias_id }
onChange={ (data) => this._handle_onTextFieldChange("contacts.postal_address", data) }
required={ true }

View File

@ -21,6 +21,8 @@ import { reduxWrapper } from '../../../../store';
import moment from "moment";
import AddressSuggests from "../../AddressSuggests";
import InputMask from 'react-input-mask';
import SuggestsInput from "../../SuggestsInput";
import { getCitizenshipTitleByCode } from "../../../../utils/citizenship";
class Form_3_Signer extends QuestionnaireForm
{
@ -70,7 +72,7 @@ class Form_3_Signer extends QuestionnaireForm
code: "",
},
registration_address: {
title: "",
name: "",
fias_id: "",
}
},
@ -106,7 +108,7 @@ class Form_3_Signer extends QuestionnaireForm
code: "",
},
registration_address: {
title: "",
name: "",
fias_id: "",
}
}
@ -140,14 +142,7 @@ class Form_3_Signer extends QuestionnaireForm
_handle_onCitizenshipChange = (name, value) =>
{
console.log("_handle_onCitizenshipChange", value);
let citizenship = undefined;
for(let i in citizenships)
{
if(parseInt(citizenships[i].value, 10) === parseInt(value, 10))
{
citizenship = citizenships[i].label;
}
}
let citizenship = getCitizenshipTitleByCode(value);
this._handle_onFieldChange(name, {
title: citizenship,
@ -320,29 +315,8 @@ class Form_3_Signer extends QuestionnaireForm
const { loading, } = this.state;
const { main, head_person, signatory_person } = this.state;
let head_person_citizenship = undefined;
if(head_person.identity_document.citizenship.code !== "")
{
for(let i in citizenships)
{
if(parseInt(citizenships[i].value, 10) === parseInt(head_person.identity_document.citizenship.code, 10))
{
head_person_citizenship = citizenships[i];
}
}
}
let signatory_person_citizenship = undefined;
if(signatory_person.identity_document.citizenship.code !== "")
{
for(let i in citizenships)
{
if(parseInt(citizenships[i].value, 10) === parseInt(signatory_person.identity_document.citizenship.code, 10))
{
signatory_person_citizenship = citizenships[i];
}
}
}
let head_person_citizenship = { label: getCitizenshipTitleByCode(head_person.identity_document.citizenship.code), code: head_person.identity_document.citizenship.code };
let signatory_person_citizenship = { label: getCitizenshipTitleByCode(signatory_person.identity_document.citizenship.code), code: signatory_person.identity_document.citizenship.code };
return (
<React.Fragment>
@ -350,6 +324,17 @@ class Form_3_Signer extends QuestionnaireForm
<p className="title">3. Информация о единоличном исполнительном органе, подписанте договора лизинга</p>
<div className="form_field">
<label>Фамилия</label>
<SuggestsInput
type="lastname"
id="head_person.lastname"
name="head_person.lastname"
value={ head_person.lastname }
placeholder="Введите фамилию"
onChange={ (value) => this._handle_onTextFieldChange("head_person.lastname", value) }
required={ true }
disabled={ checking }
/>
{/*}
<input type="text"
id="head_person.lastname"
name="head_person.lastname"
@ -359,9 +344,21 @@ class Form_3_Signer extends QuestionnaireForm
required={ true }
disabled={ checking }
/>
{*/}
</div>
<div className="form_field">
<label>Имя</label>
<SuggestsInput
type="firstname"
id="head_person.firstname"
name="head_person.firstname"
value={ head_person.firstname }
placeholder="Введите имя"
onChange={ (value) => this._handle_onTextFieldChange("head_person.firstname", value) }
required={ true }
disabled={ checking }
/>
{/*}
<input type="text"
id="head_person.firstname"
name="head_person.firstname"
@ -371,9 +368,21 @@ class Form_3_Signer extends QuestionnaireForm
required={ true }
disabled={ checking }
/>
{*/}
</div>
<div className="form_field">
<label>Отчество <small>если имеется</small></label>
<SuggestsInput
type="middlename"
id="head_person.middlename"
name="head_person.middlename"
value={ head_person.middlename }
placeholder="Введите отчество"
onChange={ (value) => this._handle_onTextFieldChange("head_person.middlename", value) }
required={ true }
disabled={ checking }
/>
{/*}
<input type="text"
id="head_person.middlename"
name="head_person.middlename"
@ -382,11 +391,12 @@ class Form_3_Signer extends QuestionnaireForm
onChange={ (event) => this._handle_onTextFieldChange(event.target.name, event.target.value) }
disabled={ checking }
/>
{*/}
</div>
<div className="formgroup">
<div className="form_field">
<label>Серия паспорта</label>
<InputMask
mask='9999'
id="head_person.identity_document.seria"
@ -395,7 +405,7 @@ class Form_3_Signer extends QuestionnaireForm
placeholder="Введите серию"
onChange={ (event) => this._handle_onTextFieldChange(event.target.name, event.target.value) }
required={ true }
disabled={ checking } >
disabled={ checking }>
</InputMask>
</div>
<div className="form_field">
@ -408,9 +418,10 @@ class Form_3_Signer extends QuestionnaireForm
placeholder="Введите номер"
onChange={ (event) => this._handle_onTextFieldChange(event.target.name, event.target.value) }
required={ true }
disabled={ checking } >
disabled={ checking }>
</InputMask>
</div>
</div>
<div className="formgroup">
<div className="form_field">
@ -426,6 +437,17 @@ class Form_3_Signer extends QuestionnaireForm
</div>
<div className="form_field">
<label>Код подразделения</label>
<InputMask
mask='999-999'
id="head_person.identity_document.code"
name="head_person.identity_document.code"
value={ head_person.identity_document.code }
placeholder="Введите код"
onChange={ (event) => this._handle_onTextFieldChange(event.target.name, event.target.value) }
required={ true }
disabled={ checking }
/>
{/*}
<input type="text"
id="head_person.identity_document.code"
name="head_person.identity_document.code"
@ -435,6 +457,7 @@ class Form_3_Signer extends QuestionnaireForm
required={ true }
disabled={ checking }
/>
{*/}
</div>
</div>
<div className="form_field">
@ -480,7 +503,7 @@ class Form_3_Signer extends QuestionnaireForm
<div className="form_field">
<label>Адрес регистрации</label>
<AddressSuggests
value={ head_person.identity_document.registration_address.title }
value={ head_person.identity_document.registration_address.name }
fias={ head_person.identity_document.registration_address.fias_id }
placeholder="Укажите адрес регистрации"
onChange={ (data) => this._handle_onTextFieldChange("head_person.identity_document.registration_address", data) }
@ -821,7 +844,7 @@ class Form_3_Signer extends QuestionnaireForm
id={ "signatory_person.identity_document.placebirth" }
value={ signatory_person.identity_document.placebirth }
placeholder="Укажите место рождения"
onChange={ (data) => this._handle_onTextFieldChange("signatory_person.identity_document.placebirth", data.title) }
onChange={ (data) => this._handle_onTextFieldChange("signatory_person.identity_document.placebirth", data.name) }
required={ true }
disabled={ checking }
/>
@ -848,7 +871,7 @@ class Form_3_Signer extends QuestionnaireForm
<div className="form_field">
<label>Адрес регистрации</label>
<AddressSuggests
value={ signatory_person.identity_document.registration_address.title }
value={ signatory_person.identity_document.registration_address.name }
fias={ signatory_person.identity_document.registration_address.fias_id }
onChange={ (data) => this._handle_onTextFieldChange("signatory_person.identity_document.registration_address", data) }
required={ true }

View File

@ -17,6 +17,7 @@ import citizenships from "../../../../lib/citizenships.json";
import { reduxWrapper } from '../../../../store';
import AddressSuggests from "../../AddressSuggests";
import InputMask from 'react-input-mask';
import { getCitizenshipTitleByCode } from "../../../../utils/citizenship";
class ShareholderForm extends React.Component
{
@ -27,15 +28,8 @@ class ShareholderForm extends React.Component
_handle_onCitizenshipChange = (name, value) =>
{
console.log("_handle_onCitizenshipChange", value);
let citizenship = undefined;
for(let i in citizenships)
{
if(parseInt(citizenships[i].value, 10) === parseInt(value, 10))
{
citizenship = citizenships[i].label;
}
}
let citizenship = getCitizenshipTitleByCode(value);
this._handle_onFieldChange(name, {
title: citizenship,
code: value,
@ -46,17 +40,7 @@ class ShareholderForm extends React.Component
{
const { index, shareholder, checking } = this.props;
let citizenship = undefined;
if(shareholder.identity_document.citizenship.code !== "")
{
for(let i in citizenships)
{
if(parseInt(citizenships[i].value, 10) === parseInt(shareholder.identity_document.citizenship.code, 10))
{
citizenship = citizenships[i];
}
}
}
let citizenship = { label: getCitizenshipTitleByCode(shareholder.identity_document.citizenship.code), code: shareholder.identity_document.citizenship.code };
return (
<React.Fragment>

View File

@ -56,6 +56,16 @@ class Form_6_NonProfit extends QuestionnaireForm
}, 10);
}
_handle_onAnother = () =>
{
const { non_profit } = this.state;
this._handle_onFieldChange("non_profit", {
fin_source_another: !non_profit.fin_source_another ? true : false,
fin_source_another_description: non_profit.fin_source_another ? "" : non_profit.fin_source_another_description,
});
}
_checkDisabled = () =>
{
const { non_profit } = this.state;
@ -142,7 +152,7 @@ class Form_6_NonProfit extends QuestionnaireForm
id="non_profit.fin_source_another"
name="non_profit.fin_source_another"
checked={ non_profit.fin_source_another }
onChange={ (event) => this._handle_onCheckboxFieldChange(event.target.name, !non_profit.fin_source_another ? true : false ) }
onChange={ (event) => this._handle_onAnother() }
disabled={ checking }
/>
<label htmlFor="non_profit.fin_source_another" style={{ width: "100%" }} className="unselectable">

View File

@ -9,26 +9,15 @@ import { SpinnerCircular } from 'spinners-react';
import debounce from 'debounce-promise';
import { set as _set, get as _get } from 'lodash';
import { updateQuestionnaire, getAddress } from "../../../actions";
import { updateQuestionnaire, getAddress, getSuggests } from "../../../actions";
const suggestsAddressDebounce = (text) =>
const suggestsAddressDebounce = (query) =>
{
return getAddress(text);
return getSuggests("address", { query });
}
const suggestsAddress = debounce(suggestsAddressDebounce, 200);
/*
const getAddress = (inputValue) => {
return
new Promise<ColourOption[]>((resolve) => {
setTimeout(() => {
resolve(filterColors(inputValue));
}, 1000);
});
}
*/
export default class QuestionnaireForm extends React.Component
{
_updateQuestionnaire = (questionnaire) =>
@ -122,23 +111,23 @@ export default class QuestionnaireForm extends React.Component
this._updateQuestionnaire(update);
}
_handle_onRemoveFile = (name, file_name) =>
_handle_onRemoveFile = (group, id) =>
{
console.log("QuestionnaireForm", "_handle_onAdd", { name, files });
const existed_files = [ ..._get(this.state, name) ];
const existed_files = [ ..._get(this.state, group) ];
console.log("QuestionnaireForm", "_handle_onRemoveFile", { group, id, existed_files });
const files = [];
for(let i in existed_files)
{
if(existed_files[i].name !== file_name)
if(existed_files[i].id !== id)
{
files.push(existed_files[i]);
}
}
const update = { ...this.state };
_set(update, name, files);
_set(update, group, files);
console.log("_handle_onRemoveFile", "group", "files", group, files);
this._updateQuestionnaire(update);
}

View File

@ -225,20 +225,20 @@ export default async function handler(req, res)
}
else if(field === "postal_address")
{
if(good(questionnaire[group].postal_address.title))
if(good(questionnaire[group].postal_address.name))
{
fields[group][field].bind = form.getTextField(fields[group][field].name);
if(fields[group][field].size !== undefined) { fields[group][field].bind.setFontSize(fields[group][field].size); }
fields[group][field].bind.setText(questionnaire[group].postal_address.title.toUpperCase());
fields[group][field].bind.setText(questionnaire[group].postal_address.name.toUpperCase());
}
}
else if(field === "fact_address")
{
if(good(questionnaire[group].fact_address.title))
if(good(questionnaire[group].fact_address.name))
{
fields[group][field].bind = form.getTextField(fields[group][field].name);
if(fields[group][field].size !== undefined) { fields[group][field].bind.setFontSize(fields[group][field].size); }
fields[group][field].bind.setText(questionnaire[group].fact_address.title.toUpperCase());
fields[group][field].bind.setText(questionnaire[group].fact_address.name.toUpperCase());
}
}
else if(field === "address_type")

View File

@ -0,0 +1,83 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import fs from 'fs';
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 { inspect } from 'util';
import multer from 'multer';
import { cors } from '../../../../lib/cors';
import RedisClient from '../../../../lib/RedisClient';
const storage = multer.memoryStorage();
const upload = multer({ storage: storage });
export default async function handler(req, res)
{
console.log("API", "questionnaire", "get");
await cors(req, res);
return new Promise((resolve) =>
{
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({ acc_number: client_jwt_decoded.acc_number }, process.env.JWT_SECRET_CRM, { noTimestamp: true });
upload.single("file")(req, {}, async (err) =>
{
console.log(req);
const { query } = req;
const { id } = query;
const local_filename = `${ client_jwt_decoded.acc_number }_${ id }`;
try
{
console.log("local_filename", local_filename);
const filename = `${ __dirname }/../../../../../../uploads/${ local_filename }`;
if (fs.existsSync(filename))
{
fs.unlinkSync(filename);
}
else
{
console.log("filename", filename);
}
res.status(200).send();
resolve();
}
catch(remove_single_error)
{
console.error("remove_single_error");
console.error(remove_single_error);
res.status(500).send();
resolve();
}
});
}
else
{
res.status(403).send();
resolve();
}
}
});
}
export const config = {
api: {
bodyParser: false
}
}

View File

@ -11,7 +11,6 @@ import { inspect } from 'util';
import multer from 'multer';
import { cors } from '../../../../lib/cors';
import RedisClient from '../../../../lib/RedisClient';
const storage = multer.memoryStorage();
const upload = multer({ storage: storage });
@ -42,7 +41,7 @@ export default async function handler(req, res)
const file_payload = {
id: id,
name: file.originalname,
name: Buffer.from(file.originalname, 'latin1').toString('utf8'),
filename: local_filename,
};

View File

@ -10,8 +10,6 @@ import { inspect } from 'util';
export default async function handler(req, res)
{
console.log("API", "questionnaire", "get");
console.log(req.body);
console.log("-".repeat(50));
await cors(req, res);
if(req.headers.cookie !== undefined)
@ -20,9 +18,6 @@ export default async function handler(req, res)
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({ acc_number: client_jwt_decoded.acc_number }, process.env.JWT_SECRET_CRM, { noTimestamp: true });
@ -30,8 +25,9 @@ export default async function handler(req, res)
try
{
const { id } = req.query;
await axios.get(path, {
params: { name: 1 },
params: { name: id },
headers: {
"Authorization": `Bearer ${ crm_jwt }`,
}

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';
import { inspect } from 'util';
import RedisClient from '../../../lib/RedisClient';
/*
"empty", #форма не заполнялась
"draft", #форма в статусе черновика с отдельным указанием заполненных этапов
"filled", #форма заполнена и готова к подписанию
"printed", #форма распечатывалась
"signed", #форма подписана ЭЦП
*/
export default async function handler(req, res)
{
console.log("API", "questionnaire", "read");
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)
{
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({ acc_number: client_jwt_decoded.acc_number }, process.env.JWT_SECRET_CRM, { noTimestamp: true });
try
{
const key = md5(`questionnaire_${ client_jwt_decoded.acc_number }`);
const questionnaire = await RedisClient.get(key);
console.error("JSON.parse(questionnaire)");
console.error(JSON.parse(questionnaire));
res.status(200).json(JSON.parse(questionnaire));
}
catch(error)
{
console.error("error");
console.error(error);
res.status(500).send();
}
}
else
{
res.status(403);
}
}
}

View File

@ -0,0 +1,64 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import https from 'https';
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';
const keepAliveAgent = new https.Agent({ keepAlive: true });
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))
{
try
{
const { seria, number } = req.body;
axios.post(`https://cleaner.dadata.ru/api/v1/clean/passport`, [ `${ seria } ${ number }` ], {
httpAgent: keepAliveAgent,
headers: {
"Content-Type": "application/json",
"Authorization": `Token ${ process.env.DADATA_API_KEY }`,
"X-Secret": process.env.DADATA_SECRET_KEY
},
})
.then((api_response) =>
{
res.status(200).send(api_response.data);
})
.catch((error) =>
{
console.log("error");
console.error(error);
res.status(500);
});
}
catch(e)
{
console.error(e);
res.status(500);
}
}
else
{
res.status(403);
}
}
else
{
res.status(403);
}
}
}

View File

@ -0,0 +1,64 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import https from 'https';
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';
const keepAliveAgent = new https.Agent({ keepAlive: true });
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))
{
try
{
const { query, } = req.body;
axios.post(`https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/fms_unit`, { query }, {
httpAgent: keepAliveAgent,
headers: {
"Content-Type": "application/json",
"Authorization": `Token ${ process.env.DADATA_API_KEY }`,
"X-Secret": process.env.DADATA_SECRET_KEY
},
})
.then((api_response) =>
{
res.status(200).send(api_response.data);
})
.catch((error) =>
{
console.log("error");
console.error(error);
res.status(500);
});
}
catch(e)
{
console.error(e);
res.status(500);
}
}
else
{
res.status(403);
}
}
else
{
res.status(403);
}
}
}

View File

@ -0,0 +1,64 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import https from 'https';
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';
const keepAliveAgent = new https.Agent({ keepAlive: true });
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))
{
try
{
const { query, } = req.body;
axios.post(`https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/fio`, { query, "parts": ["PATRONYMIC"] }, {
httpAgent: keepAliveAgent,
headers: {
"Content-Type": "application/json",
"Authorization": `Token ${ process.env.DADATA_API_KEY }`,
"X-Secret": process.env.DADATA_SECRET_KEY
},
})
.then((api_response) =>
{
res.status(200).send(api_response.data);
})
.catch((error) =>
{
console.log("error");
console.error(error);
res.status(500);
});
}
catch(e)
{
console.error(e);
res.status(500);
}
}
else
{
res.status(403);
}
}
else
{
res.status(403);
}
}
}

View File

@ -0,0 +1,64 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import https from 'https';
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';
const keepAliveAgent = new https.Agent({ keepAlive: true });
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))
{
try
{
const { query, parts } = req.body;
axios.post(`https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/fio`, { query, "parts": parts }, {
httpAgent: keepAliveAgent,
headers: {
"Content-Type": "application/json",
"Authorization": `Token ${ process.env.DADATA_API_KEY }`,
"X-Secret": process.env.DADATA_SECRET_KEY
},
})
.then((api_response) =>
{
res.status(200).send(api_response.data);
})
.catch((error) =>
{
console.log("error");
console.error(error);
res.status(500);
});
}
catch(e)
{
console.error(e);
res.status(500);
}
}
else
{
res.status(403);
}
}
else
{
res.status(403);
}
}
}

View File

@ -54,8 +54,21 @@ class QuestionnairePage extends React.Component
{
const { dispatch } = this.props;
getQuestionnaire({ dispatch });
getContractGraphicChangeSignatories({ dispatch });
setTimeout(() => {
this._init();
}, 10);
}
_init = () =>
{
const { company } = this.state;
const { dispatch } = this.props;
console.log("-".repeat(50));
console.log(company);
getQuestionnaire({ dispatch, id: company.questionnaire_id });
}
_check_fields_disabled = (values) =>

View File

@ -124,6 +124,7 @@ export const defaultState = {
},
questionnaire: {
step: 1,
status: "empty",
main: {
title: "",
inn: "",
@ -150,15 +151,15 @@ export const defaultState = {
contacts: {
address_type: "legal",
legal_address: {
title: "",
name: "",
fias_id: "",
},
fact_address: {
title: "",
name: "",
fias_id: "",
},
postal_address: {
title: "",
name: "",
fias_id: "",
},
},
@ -184,7 +185,7 @@ export const defaultState = {
code: "",
},
registration_address: {
title: "",
name: "",
fias_id: "",
}
},
@ -221,7 +222,7 @@ export const defaultState = {
code: "",
},
registration_address: {
title: "",
name: "",
fias_id: "",
}
}
@ -259,7 +260,7 @@ export const defaultState = {
code: "",
},
registration_address: {
title: "",
name: "",
fias_id: "",
}
}

View File

@ -0,0 +1,15 @@
import citizenships from "../../lib/citizenships.json";
export function getCitizenshipTitleByCode(value)
{
let citizenship = undefined;
for(let i in citizenships)
{
if(parseInt(citizenships[i].value, 10) === parseInt(value, 10))
{
citizenship = citizenships[i].label;
}
}
return citizenship;
}