From bb20056ca9897518194118cd56367f140790e621 Mon Sep 17 00:00:00 2001 From: merelendor Date: Thu, 8 Sep 2022 08:37:39 +0300 Subject: [PATCH] faq search, events search --- actions/supportActions.js | 18 ++- constants/actionTypes.js | 2 +- css/main/style.css | 86 +++++++++++++++ css/main/style.less | 95 ++++++++++++++++ pages/contract/index.js | 6 +- pages/events.js | 25 ++++- pages/support/index.js | 219 +++++++++++++++++++++++++++---------- pages/support/request.js | 85 ++++++++++++-- reducers/initialState.js | 2 +- reducers/supportReducer.js | 4 +- 10 files changed, 464 insertions(+), 78 deletions(-) diff --git a/actions/supportActions.js b/actions/supportActions.js index 0e20589..a29366c 100644 --- a/actions/supportActions.js +++ b/actions/supportActions.js @@ -88,7 +88,14 @@ export const getSupportThemes = ({ dispatch, query, }) => .then(async (response) => { console.log("getContractRules", "response.data", response.data); - dispatch({ type: actionTypes.SUPPORT_THEMES, data: { themes: response.data.themes } }); + if(query !== undefined) + { + dispatch({ type: actionTypes.SUPPORT_THEMES_FILTERED, data: { filtered: response.data.themes } }); + } + else + { + dispatch({ type: actionTypes.SUPPORT_THEMES, data: { themes: response.data.themes } }); + } resolve(); }) @@ -100,6 +107,15 @@ export const getSupportThemes = ({ dispatch, query, }) => }); } +export const resetFilteredThemes = ({ dispatch }) => +{ + return new Promise((resolve, reject) => + { + dispatch({ type: actionTypes.SUPPORT_THEMES_FILTERED, data: { filtered: null } }); + resolve(); + }); +} + export const sendNewAppeal = (appeal) => { console.log("ACTION", "support", "sendNewAppeal", appeal); diff --git a/constants/actionTypes.js b/constants/actionTypes.js index ec79156..b88fc01 100644 --- a/constants/actionTypes.js +++ b/constants/actionTypes.js @@ -35,7 +35,7 @@ export const EVENTS_FILTERED = 'EVENTS_FILTERED'; export const EVENTS_RESET = 'EVENTS_RESET'; export const SUPPORT_THEMES = 'SUPPORT_THEMES'; -export const SUPPORT_THEMES_SEARCHED = 'SUPPORT_THEMES_SEARCHED'; +export const SUPPORT_THEMES_FILTERED = 'SUPPORT_THEMES_FILTERED'; export const SUPPORT_APPEALS = 'SUPPORT_APPEALS'; export const SUPPORT_APPEAL = 'SUPPORT_APPEAL'; export const SUPPORT_RESET = 'SUPPORT_RESET'; \ No newline at end of file diff --git a/css/main/style.css b/css/main/style.css index 0c0cf7b..28d3c7d 100644 --- a/css/main/style.css +++ b/css/main/style.css @@ -5014,3 +5014,89 @@ main .dropdown_blocks_list.zero-margin.gibdd .dropdown_block .block_body .fines_ min-width: 195px; } } +@media all and (max-width: 1280px) { + .contract_payments_status_cell { + border-top: unset!important; + } +} +@media all and (max-width: 1280px) { + .contract_payments_invoices_cell { + flex-direction: column; + width: 100%; + display: flex; + white-space: nowrap; + min-width: 100% !important; + } + .contract_payments_invoices_cell p { + white-space: nowrap!important; + display: flex; + } + .contract_payments_invoices_cell p span { + white-space: nowrap; + padding-left: 10px; + margin-top: 0px!important; + } +} +@media all and (max-width: 900px) { + .contract_payments_invoices_cell { + flex-direction: column; + width: 100%; + display: flex; + white-space: nowrap; + min-width: 100% !important; + } + .contract_payments_invoices_cell p { + white-space: normal!important; + display: flex; + flex-direction: column; + } + .contract_payments_invoices_cell p span { + padding-left: 0px; + } +} +@media all and (max-width: 768px) { + .contract_payments_invoices_cell { + flex-direction: column; + width: 100%; + display: flex; + white-space: nowrap; + min-width: 100% !important; + } + .contract_payments_invoices_cell p { + flex-direction: row; + white-space: nowrap!important; + display: flex; + } + .contract_payments_invoices_cell p span { + white-space: nowrap; + padding-left: 10px; + margin-top: 0px!important; + } +} +@media all and (max-width: 400px) { + .contract_payments_invoices_cell { + flex-direction: column; + width: 100%; + display: flex; + white-space: nowrap; + min-width: 100% !important; + } + .contract_payments_invoices_cell p { + white-space: normal!important; + display: flex; + flex-direction: column; + } + .contract_payments_invoices_cell p span { + padding-left: 0px; + } +} +.search_form_buttons_wrapper { + flex-direction: row; + display: flex; + align-items: flex-start; + justify-content: flex-end; + margin-left: auto; +} +.search_form_buttons_wrapper .button { + display: block!important; +} diff --git a/css/main/style.less b/css/main/style.less index cf3b388..88f6dbf 100644 --- a/css/main/style.less +++ b/css/main/style.less @@ -5662,4 +5662,99 @@ main .dropdown_blocks_list .dropdown_block .block_body { @media all and (max-width: 1600px) { min-width: 195px; } +} + +.contract_payments_status_cell { + @media all and (max-width: 1280px) { + border-top: unset!important; + } +} + +.contract_payments_invoices_cell { + @media all and (max-width: 1280px) { + flex-direction: column; + width: 100%; + display: flex; + white-space: nowrap; + min-width: 100% !important; + + p { + white-space: nowrap!important; + display: flex; + + span { + white-space: nowrap; + padding-left: 10px; + margin-top: 0px!important; + } + } + } + + @media all and (max-width: 900px) { + flex-direction: column; + width: 100%; + display: flex; + white-space: nowrap; + min-width: 100% !important; + + p { + white-space: normal!important; + display: flex; + flex-direction: column; + + span { + padding-left: 0px; + } + } + } + + @media all and (max-width: 768px) { + flex-direction: column; + width: 100%; + display: flex; + white-space: nowrap; + min-width: 100% !important; + + p { + flex-direction: row; + white-space: nowrap!important; + display: flex; + + span { + white-space: nowrap; + padding-left: 10px; + margin-top: 0px!important; + } + } + } + + @media all and (max-width: 400px) { + flex-direction: column; + width: 100%; + display: flex; + white-space: nowrap; + min-width: 100% !important; + + p { + white-space: normal!important; + display: flex; + flex-direction: column; + + span { + padding-left: 0px; + } + } + } +} + +.search_form_buttons_wrapper { + flex-direction: row; + display: flex; + align-items: flex-start; + justify-content: flex-end; + margin-left: auto; + + .button { + display: block!important; + } } \ No newline at end of file diff --git a/pages/contract/index.js b/pages/contract/index.js index 073ab02..6c975fc 100644 --- a/pages/contract/index.js +++ b/pages/contract/index.js @@ -256,7 +256,7 @@ class ContractSchedulePage extends React.Component
{ moment(payment.date, "DD-MM-YYYY").format("DD.MM.YYYY") }
{ numeral(payment.total_amount).format(' ., ') } ₽
{ numeral(payment.vat_amount).format(' ., ') } ₽
-
+
{ payment.status === "Paid" && "Оплачено" } { payment.status === "NotPaid" && "Не оплачено" } { payment.status === "HalfPaid" && ( @@ -266,11 +266,11 @@ class ContractSchedulePage extends React.Component <>Переплата { numeral(payment.total_amount).format(' ., ') } ₽ ) }
-
+
{ payment.invoices !== undefined && payment.invoices.map((invoice, invoice_index) => ( -

№{ invoice.number } от { moment(invoice.date, "DD-MM-YYYY").format("DD.MM.YYYY") } на сумму { numeral(invoice.total_amount).format(' ., ') } ₽

+

№{ invoice.number } от { moment(invoice.date, "DD-MM-YYYY").format("DD.MM.YYYY") } на сумму: { numeral(invoice.total_amount).format(' ., ') } ₽

)) }
diff --git a/pages/events.js b/pages/events.js index 4910c19..d9be01a 100644 --- a/pages/events.js +++ b/pages/events.js @@ -39,7 +39,8 @@ class EventsPage extends React.Component "return_pts": "pts", }, loading: false, - search: "" + search: "", + searched: false, }; } @@ -89,7 +90,18 @@ class EventsPage extends React.Component _handle_onSearch = () => { - this._filterEvents(); + this.setState({ searched: true }, () => + { + this._filterEvents(); + }); + } + + _handle_onSearchReset = () => + { + this.setState({ searched: false, search: "" }, () => + { + this._filterEvents(); + }); } _filterEvents = () => @@ -133,7 +145,7 @@ class EventsPage extends React.Component render() { - const { loading, type, types, search, events, events_loaded, filtered } = this.state; + const { loading, type, types, search, events, events_loaded, filtered, searched } = this.state; console.log("events", "type", type); return ( @@ -160,7 +172,12 @@ class EventsPage extends React.Component this._handle_onChange_search(event.target.value); } }/>
- +
+ + { searched && ( + + ) } +
{ events_loaded && ( diff --git a/pages/support/index.js b/pages/support/index.js index ba555ef..487772e 100644 --- a/pages/support/index.js +++ b/pages/support/index.js @@ -17,6 +17,7 @@ import TemplateFile from "./components/TemplateFile"; import { getSupportThemes, + resetFilteredThemes, } from "../../actions"; class ContractPage extends React.Component @@ -29,9 +30,11 @@ class ContractPage extends React.Component question_selected: undefined, appeals: null, appeal: null, - searched: null, + filtered: null, loading: false, + search: "", query: "", + searched: false, }; this.question_refs = []; @@ -43,7 +46,7 @@ class ContractPage extends React.Component themes: nextProps.themes, appeals: nextProps.appeals, appeal: nextProps.appeal, - searched: nextProps.searched, + filtered: nextProps.filtered, }; } @@ -63,9 +66,10 @@ class ContractPage extends React.Component { for(let q in this.state.themes[t].questions) { + this.question_refs[this.state.themes[t].questions[q].id] = React.createRef(); + if(this.props.router.asPath.indexOf(this.state.themes[t].questions[q].id) > -1) { - this.question_refs[this.state.themes[t].questions[q].id] = React.createRef(); question_selected = this.state.themes[t].questions[q].id; found = true; } @@ -113,13 +117,89 @@ class ContractPage extends React.Component _handle_onChangeSearchQuery = (value) => { - this.setState({ query: value }); + this.setState({ search: value }); } - + + _handle_onSearch = () => + { + const { search } = this.state; + + this.setState({ searched: true, query: search }, () => + { + getSupportThemes({ dispatch: this.props.dispatch, query: search }) + .then(() => + { + }); + }); + } + + _handle_onSearchReset = () => + { + this.setState({ searched: false, search: "", query: "" }); + } + + _handle_onLocalLink = (id) => + { + const { dispatch } = this.props; + + window.location = `/support/faq#${ id }`; + this.setState({ searched: false, search: "", query: "", question_selected: id }, () => + { + resetFilteredThemes({ dispatch }); + setTimeout(() => { + this.question_refs[id].current.scrollIntoView({ + behavior: 'smooth', + block: 'center', + }); + }, 100); + }); + } + + _getMarks = (content) => + { + const { query } = this.state; + const search_array = query.split(" "); + + const chunks = []; + const content_array = content.split(" "); + + for(let i in content_array) + { + let found = false; + for(let s in search_array) + { + if(content_array[i].toLowerCase() == search_array[s].toLowerCase()) + { + found = true; + } + } + + if(found) + { + chunks.push(`${ content_array[i] }`); + } + else + { + chunks.push(content_array[i]); + } + } + + return chunks.join(" "); + } + render() { - const { loading, themes, question_selected, searched, appleals, query } = this.state; - console.log("themes", themes); + //filtered, + const { loading, themes, filtered, question_selected, searched, appleals, search } = this.state; + + let filtered_count = 0; + if(filtered !== undefined && filtered !== null) + { + for(let i in filtered) + { + filtered_count = filtered_count + filtered[i].questions.length; + } + } return ( @@ -147,66 +227,91 @@ class ContractPage extends React.Component
{ event.preventDefault(); }}>
- { this._handle_onChangeSearchQuery(event.target.value);} }/> + { this._handle_onChangeSearchQuery(event.target.value);} }/> +
+
+ + { searched && ( + + ) }
-
-
- { themes !== undefined && themes !== null && themes.map((theme) => - ( -
-

{ theme.name }

-
- { theme.questions.map((question) => - ( -
-
this._handle_onQuestion(question.id) }> -

{ question.title }

- -
-
-
-
-

Процедура

-

+ {/* Результат поиска */} + { searched && filtered !== undefined && filtered !== null ? ( + <> + { filtered_count > 0 ? ( + <> + { filtered.map((theme, theme_index) => ( + + { theme.questions.map((question, index) => + ( +

+
+

+

+ {/*} +

К каждой теме свободное html поле для миниинструкции (со ссылками на формы документов и документы). Привязка к теме обращения в CRM

+ {*/} +
- { question.documents !== null && ( +
+ )) } + + )) } + + ) : ( +

К сожалению по Вашему запросу нет результатов.

+ ) } + + ) : ( +
+ { themes !== undefined && themes !== null && themes.map((theme) => + ( +
+

{ theme.name }

+
+ { theme.questions.map((question) => + ( +
+
this._handle_onQuestion(question.id) }> +

{ question.title }

+ +
+
+
-

Документы

-

+

Процедура

+

- ) } - { question.templates !== null && ( -
-

Шаблоны документов

-
- { question.templates.map((template, index) => ()) } + { question.documents !== null && ( +
+

Документы

+

-
- ) } - { question.request && ( - - ) } + ) } + { question.templates !== null && ( +
+

Шаблоны документов

+
+ { question.templates.map((template, index) => ()) } +
+
+ ) } + { question.request && ( + + ) } +
-
- )) } + )) } +
-
- )) } -
- {/* Результат поиска */} - { searched !== undefined && searched !== null && searched.map((question) => ( -
-
-

{ question.theme } / { question.name }

-

К каждой теме свободное html поле для миниинструкции (со ссылками на формы документов и документы). Привязка к теме обращения в CRM

-
+ )) }
- )) } + ) } ) } @@ -222,7 +327,7 @@ function mapStateToProps(state, ownProps) { return { themes: state.support.themes, - searched: state.support.searched, + filtered: state.support.filtered, appeals: state.support.appeals, appeal: state.support.appeal, }; diff --git a/pages/support/request.js b/pages/support/request.js index 74ec3d5..ffcd883 100644 --- a/pages/support/request.js +++ b/pages/support/request.js @@ -81,6 +81,7 @@ class SupportRequestPage extends React.Component phone: "", email: "", question: "", + all_contracts: false, selected_contracts: [], file: null, files: [], @@ -200,11 +201,17 @@ class SupportRequestPage extends React.Component this.setState({ loading: true }, () => { + const contract_numbers = []; + for(let i in selected_contracts) + { + contract_numbers.push(selected_contracts.value); + } + sendNewAppeal({ phone: phone, email: email, description: question, - contract_numbers: selected_contracts + contract_numbers: contract_numbers }) .then((result) => { @@ -245,11 +252,61 @@ class SupportRequestPage extends React.Component _handle_onContract = (options) => { + const { contracts, all_contracts } = this.state; const selected_contracts = []; - for(let i in options) + console.log("options", options); + + if(all_contracts === true) { - selected_contracts.push(options[i].value); - this.setState({ selected_contracts }); + this.setState({ all_contracts: false, selected_contracts: [] }); + } + else + { + let all = false; + for(let i in options) + { + if(options[i].value === null) + { + all = true; + break; + } + } + + if(all) + { + const contracts_list = []; + for(let i in contracts) + { + contracts_list.push({ value: contracts[i].number, label: contracts[i].number }); + } + + this.setState({ all_contracts: true, selected_contracts: contracts_list }); + } + else + { + if(options.length === contracts.length) + { + const contracts_list = []; + for(let i in contracts) + { + contracts_list.push({ value: contracts[i].number, label: contracts[i].number }); + } + + this.setState({ all_contracts: true, selected_contracts: contracts_list }); + } + else + { + this.setState({ selected_contracts: options }); + } + + /* + for(let i in options) + { + selected_contracts.push(options[i].value); + this.setState({ selected_contracts }); + } + */ + } } } @@ -302,14 +359,23 @@ class SupportRequestPage extends React.Component _renderForm = () => { - const { loading, contracts, themes, themes_filtered, name, phone, email, question, file, files, opened_theme, opened_question } = this.state; + const { loading, contracts, selected_contracts, all_contracts, themes, themes_filtered, name, phone, email, question, file, files, opened_theme, opened_question } = this.state; const contracts_list = []; - for(let i in contracts) + if(!all_contracts) { - contracts_list.push({ - value: contracts[i].number, label: contracts[i].number - }); + for(let i in contracts) + { + contracts_list.push({ + value: contracts[i].number, label: contracts[i].number + }); + } + + contracts_list.unshift({ value: null, label: "Все договоры" }); + } + else + { + contracts_list.unshift({ value: null, label: "Все договоры" }); } return ( @@ -322,6 +388,7 @@ class SupportRequestPage extends React.Component classNamePrefix="custom-select" placeholder="Выберите договоры" onChange={ this._handle_onContract } + value={ all_contracts ? contracts_list : selected_contracts } />
diff --git a/reducers/initialState.js b/reducers/initialState.js index 6d5b38e..fd16fbd 100644 --- a/reducers/initialState.js +++ b/reducers/initialState.js @@ -94,7 +94,7 @@ export const defaultState = { support: { themes: null, - searched: null, + filtered: null, appeals: { list: null, new: 0 }, appeal: null, request: null, diff --git a/reducers/supportReducer.js b/reducers/supportReducer.js index 0018c4a..73b3681 100644 --- a/reducers/supportReducer.js +++ b/reducers/supportReducer.js @@ -23,11 +23,11 @@ const supportReducer = (state = initialState.support, action) => }; } - case actionTypes.SUPPORT_THEMES_SEARCHED: + case actionTypes.SUPPORT_THEMES_FILTERED: { return { ...state, - searched: action.data.searched, + filtered: action.data.filtered, }; }