hl-core 0.0.9-beta.9 → 0.0.10-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/api/base.api.ts +1110 -0
  2. package/api/index.ts +2 -620
  3. package/api/interceptors.ts +38 -1
  4. package/components/Button/Btn.vue +1 -6
  5. package/components/Complex/MessageBlock.vue +1 -1
  6. package/components/Complex/Page.vue +1 -1
  7. package/components/Complex/TextBlock.vue +25 -0
  8. package/components/Dialog/Dialog.vue +72 -16
  9. package/components/Dialog/FamilyDialog.vue +3 -1
  10. package/components/Form/DynamicForm.vue +101 -0
  11. package/components/Form/FormBlock.vue +12 -3
  12. package/components/Form/FormData.vue +111 -0
  13. package/components/Form/FormSection.vue +3 -3
  14. package/components/Form/FormTextSection.vue +11 -3
  15. package/components/Form/FormToggle.vue +25 -5
  16. package/components/Form/ManagerAttachment.vue +178 -89
  17. package/components/Form/ProductConditionsBlock.vue +59 -6
  18. package/components/Input/Datepicker.vue +43 -7
  19. package/components/Input/DynamicInput.vue +25 -0
  20. package/components/Input/FileInput.vue +25 -5
  21. package/components/Input/FormInput.vue +9 -4
  22. package/components/Input/Monthpicker.vue +34 -0
  23. package/components/Input/PanelInput.vue +6 -1
  24. package/components/Input/RoundedInput.vue +2 -0
  25. package/components/Input/RoundedSelect.vue +9 -2
  26. package/components/Input/SwitchInput.vue +66 -0
  27. package/components/Input/TextInput.vue +162 -0
  28. package/components/Layout/Drawer.vue +18 -4
  29. package/components/Layout/Header.vue +23 -2
  30. package/components/Layout/Loader.vue +2 -1
  31. package/components/Layout/SettingsPanel.vue +24 -11
  32. package/components/Menu/InfoMenu.vue +35 -0
  33. package/components/Menu/MenuNav.vue +25 -3
  34. package/components/Pages/Anketa.vue +255 -65
  35. package/components/Pages/Auth.vue +58 -9
  36. package/components/Pages/ContragentForm.vue +10 -9
  37. package/components/Pages/Documents.vue +267 -30
  38. package/components/Pages/InvoiceInfo.vue +1 -1
  39. package/components/Pages/MemberForm.vue +775 -102
  40. package/components/Pages/ProductAgreement.vue +1 -8
  41. package/components/Pages/ProductConditions.vue +1133 -180
  42. package/components/Panel/PanelHandler.vue +627 -49
  43. package/components/Panel/PanelSelectItem.vue +17 -2
  44. package/components/Panel/RightPanelCloser.vue +7 -0
  45. package/components/Transitions/Animation.vue +30 -0
  46. package/components/Utilities/Chip.vue +2 -0
  47. package/components/Utilities/JsonViewer.vue +2 -2
  48. package/components/Utilities/Qr.vue +44 -0
  49. package/composables/axios.ts +1 -0
  50. package/composables/classes.ts +550 -44
  51. package/composables/constants.ts +126 -6
  52. package/composables/fields.ts +330 -0
  53. package/composables/index.ts +356 -20
  54. package/composables/styles.ts +23 -6
  55. package/configs/pwa.ts +63 -0
  56. package/layouts/clear.vue +21 -0
  57. package/layouts/default.vue +62 -3
  58. package/layouts/full.vue +21 -0
  59. package/locales/ru.json +558 -16
  60. package/nuxt.config.ts +6 -15
  61. package/package.json +38 -39
  62. package/pages/Token.vue +0 -13
  63. package/plugins/head.ts +26 -0
  64. package/plugins/vuetifyPlugin.ts +1 -5
  65. package/store/data.store.ts +1647 -348
  66. package/store/extractStore.ts +17 -0
  67. package/store/form.store.ts +13 -1
  68. package/store/member.store.ts +2 -1
  69. package/store/rules.ts +97 -3
  70. package/store/toast.ts +1 -1
  71. package/tsconfig.json +3 -0
  72. package/types/enum.ts +82 -0
  73. package/types/env.d.ts +2 -0
  74. package/types/form.ts +90 -0
  75. package/types/index.ts +847 -506
@@ -1,6 +1,9 @@
1
1
  <template>
2
2
  <base-fade-transition>
3
- <section v-if="firstQuestionList && firstQuestionList.length && !firstPanel && !secondPanel" class="flex flex-col">
3
+ <section v-if="firstQuestionList && firstQuestionList.length && (isFirstPanelOnRight ? true : !firstPanel) && !secondPanel" class="flex flex-col shrink grow max-h-[90vh]">
4
+ <base-form-section v-if="$dataStore.isUnderwriter()" class="mx-[10px]">
5
+ <base-rounded-select v-model="filterType" class="w-[200px]" :items="filterItems" :label="$dataStore.t('labels.filter')" hide-details />
6
+ </base-form-section>
4
7
  <section :class="[$styles.blueBgLight, $styles.rounded]" class="mx-[10px] my-[14px] p-4 flex flex-col gap-4">
5
8
  <base-form-toggle
6
9
  v-model="answerToAll"
@@ -10,7 +13,7 @@
10
13
  @clicked="handleToggler"
11
14
  />
12
15
  </section>
13
- <v-form ref="vForm" class="max-h-[70vh] overflow-y-scroll" @submit="submitForm">
16
+ <v-form ref="vForm" class="grow shrink overflow-y-scroll" @submit="submitForm">
14
17
  <section
15
18
  v-if="firstQuestionList.filter(i => i.first.definedAnswers === 'N').length"
16
19
  :class="[$styles.blueBgLight, $styles.rounded]"
@@ -27,30 +30,34 @@
27
30
  />
28
31
  </section>
29
32
  <section
30
- v-if="firstQuestionList.filter(i => i.first.definedAnswers === 'Y').length"
33
+ v-if="firstQuestions.filter(i => i.first.definedAnswers === 'Y').length"
31
34
  :class="[$styles.blueBgLight, $styles.rounded]"
32
35
  class="mx-[10px] mt-[14px] p-4 flex flex-col gap-4"
33
36
  >
34
- <base-form-text-section v-for="(question, index) in firstQuestionList.filter(i => i.first.definedAnswers === 'Y')" :key="index">
35
- <base-fade-transition>
37
+ <base-form-text-section
38
+ v-for="(question, index) in firstQuestions.filter(i => i.first.definedAnswers === 'Y')"
39
+ :key="index"
40
+ :class="[currentQuestion?.first.id === question.first.id && $dataStore.rightPanel.open ? $styles.greenBorder : '']"
41
+ >
42
+ <base-animation>
36
43
  <div
37
- v-if="question.first.answerName === 'Да' && secondQuestionList"
44
+ v-if="question.first.answerName === 'Да' && question.second"
38
45
  :class="[$styles.greenBg, $styles.whiteText, $styles.textSimple]"
39
46
  class="rounded-t-lg pl-6 py-1 cursor-pointer"
40
47
  @click="openFirstPanel(question)"
41
48
  >
42
- {{ $dataStore.t('questionnaireType.pleaseAnswer', { text: secondQuestionList.length }) }}
49
+ {{ $dataStore.t('questionnaireType.pleaseAnswer', { text: question.second.length }) }}
43
50
  </div>
44
- </base-fade-transition>
51
+ </base-animation>
45
52
  <span :class="[$styles.textTitle]" class="border-b-[1px] border-b-[#F3F6FC] p-6 flex items-center justify-between">
46
53
  {{ question.first.name }}
47
- <base-fade-transition>
54
+ <base-animation>
48
55
  <i
49
- v-if="question.first.answerName === 'Да' && secondQuestionList && secondQuestionList.length"
56
+ v-if="question.first.answerName === 'Да' && question.second && question.second.length"
50
57
  class="mdi mdi-chevron-right text-2xl cursor-pointer"
51
58
  @click="openFirstPanel(question)"
52
59
  ></i>
53
- </base-fade-transition>
60
+ </base-animation>
54
61
  </span>
55
62
  <div class="flex items-center justify-start gap-5 px-4 pt-4" :class="[$styles.textSimple]">
56
63
  <v-radio-group
@@ -68,43 +75,108 @@
68
75
  </div>
69
76
  </base-form-text-section>
70
77
  </section>
78
+ <section
79
+ v-if="firstQuestions.filter(i => i.first.definedAnswers === 'D').length"
80
+ :class="[$styles.blueBgLight, $styles.rounded]"
81
+ class="mx-[10px] mt-[14px] p-4 flex flex-col gap-4"
82
+ >
83
+ <base-form-text-section
84
+ v-for="(question, index) in firstQuestions.filter(i => i.first.definedAnswers === 'D')"
85
+ :key="index"
86
+ :class="[currentQuestion?.first.id === question.first.id && $dataStore.rightPanel.open ? $styles.greenBorder : '']"
87
+ >
88
+ <span :class="[$styles.textTitle]" class="border-b-[1px] border-b-[#F3F6FC] p-6 flex items-center justify-between"> {{ question.first.name }} </span>
89
+ <div class="flex items-center justify-start gap-5 px-4 pt-4" :class="[$styles.textSimple]">
90
+ <v-radio-group
91
+ v-model="question.first.answerName"
92
+ class="anketa-radio"
93
+ :true-icon="`mdi-radiobox-marked ${$styles.greenText}`"
94
+ false-icon="mdi-radiobox-blank text-[#636363]"
95
+ :rules="$rules.required"
96
+ :readonly="formStore.isDisabled[whichSurvey] || !$dataStore.isTask()"
97
+ inline
98
+ >
99
+ <v-radio label="Да" value="Да" />
100
+ <v-radio label="Нет" value="Нет" />
101
+ </v-radio-group>
102
+ </div>
103
+ <base-animation>
104
+ <div v-if="question.first.answerName === 'Да'" :class="[$styles.whiteText, $styles.textSimple]">
105
+ <base-form-input
106
+ v-model="question.first.answerText"
107
+ :label="$dataStore.t('labels.inDetails')"
108
+ :readonly="formStore.isDisabled[whichSurvey] || !$dataStore.isTask()"
109
+ :rules="$rules.required"
110
+ />
111
+ </div>
112
+ </base-animation>
113
+ </base-form-text-section>
114
+ </section>
71
115
  </v-form>
72
- <base-btn
73
- class="my-[14px] self-center"
74
- :loading="isButtonLoading"
75
- :disabled="formStore.isDisabled[whichSurvey] || !$dataStore.isTask()"
76
- @click="submitForm"
77
- :text="$dataStore.t('buttons.save')"
78
- />
116
+ <div class="px-[14px]">
117
+ <base-btn
118
+ class="my-[14px] self-center"
119
+ :loading="isButtonLoading"
120
+ :disabled="formStore.isDisabled[whichSurvey] || !$dataStore.isTask()"
121
+ @click="submitForm"
122
+ :text="$dataStore.t('buttons.save')"
123
+ />
124
+ </div>
79
125
  </section>
80
- <v-btn
81
- v-if="secondQuestionList && secondQuestionList.length && firstPanel"
82
- icon="mdi mdi-close"
83
- class="ml-3 !absolute z-10"
84
- @click="
85
- firstPanel = false;
86
- secondPanel = false;
87
- "
126
+ <base-btn
127
+ v-if="currentQuestion && currentQuestion.second && currentQuestion.second.length && isFirstPanelOnRight ? false : firstPanel"
128
+ class="!absolute z-10 self-center w-[96%] bottom-0"
129
+ :text="$dataStore.t('buttons.save')"
130
+ @click="submitSecondaryForm"
88
131
  />
89
- <section ref="firstPanelSection" v-if="secondQuestionList && secondQuestionList.length && firstPanel" class="flex flex-col px-[10px] pb-[14px]" :class="[$styles.scrollPage]">
90
- <section v-if="currentQuestion" :class="[$styles.blueBgLight, $styles.rounded]" class="mx-[10px] mt-[14px] p-4 flex flex-col gap-4">
132
+ <section
133
+ ref="firstPanelSection"
134
+ v-if="currentQuestion && currentQuestion.second && isFirstPanelOnRight ? false : firstPanel"
135
+ class="flex flex-col px-[10px] pb-[14px]"
136
+ :class="[$styles.scrollPage]"
137
+ >
138
+ <v-form
139
+ v-if="currentQuestion"
140
+ :class="[$styles.blueBgLight, $styles.rounded]"
141
+ class="mx-[10px] mt-[14px] p-4 flex flex-col gap-4"
142
+ ref="vSecondaryForm"
143
+ @submit="submitSecondaryForm"
144
+ >
91
145
  <base-form-text-section v-for="question in currentQuestion.second" :title="question.name" :key="question.name">
92
- <base-form-input
93
- v-if="question.definedAnswers === 'N'"
94
- v-model="question.answerText"
95
- class="border-t-[1px] border-t-[#F3F6FC]"
96
- placeholder="Введите текст"
146
+ <div v-if="question.definedAnswers === 'N'">
147
+ <base-form-input
148
+ v-if="question.answerType === 'T' || question.answerType === 'N'"
149
+ v-model="question.answerText"
150
+ class="border-t-[1px] border-t-[#F3F6FC]"
151
+ :placeholder="$dataStore.t('labels.inputText')"
152
+ :readonly="formStore.isDisabled[whichSurvey] || !$dataStore.isTask()"
153
+ :rules="isSecondRequired ? $rules.required : []"
154
+ />
155
+ <base-form-input
156
+ v-if="question.answerType === 'D'"
157
+ v-model="question.answerText"
158
+ class="border-t-[1px] border-t-[#F3F6FC]"
159
+ :placeholder="$dataStore.t('form.date')"
160
+ :readonly="formStore.isDisabled[whichSurvey] || !$dataStore.isTask()"
161
+ :rules="isSecondRequired ? $rules.date : []"
162
+ :maska="$maska.date"
163
+ append-inner-icon="mdi mdi-calendar-blank-outline"
164
+ />
165
+ </div>
166
+ <base-panel-input
167
+ v-else
168
+ :class="[$styles.textTitle, $styles.greenText]"
169
+ :value="question.answerName ? question.answerName : 'Выбрать вариант ответа'"
97
170
  :readonly="formStore.isDisabled[whichSurvey] || !$dataStore.isTask()"
98
- />
99
- <span v-else class="flex items-center justify-between p-4 cursor-pointer" :class="[$styles.textTitle, $styles.greenText]" @click="openSecondPanel(question)">
100
- {{ question.answerName ? question.answerName : 'Выбрать вариант ответа' }}
101
- <i class="mdi mdi-chevron-right text-[28px]"></i>
102
- </span>
171
+ :clearable="false"
172
+ :error-messages="isSecondRequired ? (question.answerName ? [] : ['Выбрать вариант ответа']) : []"
173
+ @click="openSecondPanel(question)"
174
+ ></base-panel-input>
103
175
  </base-form-text-section>
104
- </section>
176
+ </v-form>
105
177
  </section>
106
178
  </base-fade-transition>
107
- <Teleport v-if="secondPanel" to="#panel-actions">
179
+ <Teleport v-if="secondPanel" to="#right-panel-actions">
108
180
  <div :class="[$styles.scrollPage]" class="flex flex-col items-center">
109
181
  <base-rounded-input v-model="searchQuery" :label="$dataStore.t('labels.search')" class="w-full p-2" :hide-details="true" />
110
182
  <div v-if="$dataStore.questionRefs && $dataStore.questionRefs.length && isPanelLoading === false" class="w-full flex flex-col gap-2 p-2">
@@ -119,11 +191,55 @@
119
191
  <base-loader v-if="isPanelLoading" class="absolute mt-10" :size="50" />
120
192
  </div>
121
193
  </Teleport>
122
- <base-scroll-buttons @up="scrollForm('up')" @down="scrollForm('down')" />
194
+ <Teleport v-if="isFirstPanelOnRight && firstPanel" to="#right-panel-actions">
195
+ <div :class="$styles.scrollPage">
196
+ <v-form
197
+ v-if="currentQuestion"
198
+ :class="[$styles.blueBgLight, $styles.rounded]"
199
+ class="mx-[10px] mt-[14px] p-4 flex flex-col gap-4"
200
+ ref="vSecondaryForm"
201
+ @submit="submitSecondaryForm"
202
+ >
203
+ <base-form-text-section v-for="question in currentQuestion.second" :title="question.name" :key="question.name" :title-class="$styles.textSimple">
204
+ <div v-if="question.definedAnswers === 'N'">
205
+ <base-form-input
206
+ v-if="question.answerType === 'T' || question.answerType === 'N'"
207
+ v-model="question.answerText"
208
+ class="border-t-[1px] border-t-[#F3F6FC]"
209
+ :placeholder="$dataStore.t('labels.inputText')"
210
+ :readonly="formStore.isDisabled[whichSurvey] || !$dataStore.isTask()"
211
+ :rules="isSecondRequired ? $rules.required : []"
212
+ />
213
+ <base-form-input
214
+ v-if="question.answerType === 'D'"
215
+ v-model="question.answerText"
216
+ class="border-t-[1px] border-t-[#F3F6FC]"
217
+ :placeholder="$dataStore.t('form.date')"
218
+ :readonly="formStore.isDisabled[whichSurvey] || !$dataStore.isTask()"
219
+ :rules="isSecondRequired ? $rules.date : []"
220
+ :maska="$maska.date"
221
+ append-inner-icon="mdi mdi-calendar-blank-outline"
222
+ />
223
+ </div>
224
+ <base-panel-input
225
+ v-else
226
+ :class="[$styles.greenText]"
227
+ :value="question.answerName ? question.answerName : 'Выбрать вариант ответа'"
228
+ :readonly="formStore.isDisabled[whichSurvey] || !$dataStore.isTask()"
229
+ :clearable="false"
230
+ :error-messages="isSecondRequired ? (question.answerName ? [] : ['Выбрать вариант ответа']) : []"
231
+ @click="openSecondPanel(question)"
232
+ />
233
+ </base-form-text-section>
234
+ </v-form>
235
+ </div>
236
+ </Teleport>
237
+ <base-scroll-buttons v-if="firstQuestionList && firstQuestionList.length" @up="scrollForm('up')" @down="scrollForm('down')" />
123
238
  </template>
124
239
 
125
240
  <script lang="ts">
126
241
  import { Value } from '../../composables/classes';
242
+ import type { AnketaBody, AnketaSecond, AnswerName } from '../../types';
127
243
 
128
244
  export default defineComponent({
129
245
  setup() {
@@ -132,11 +248,18 @@ export default defineComponent({
132
248
  const formStore = useFormStore();
133
249
  const dataStore = useDataStore();
134
250
  const vForm = ref<any>();
251
+ const vSecondaryForm = ref<any>();
135
252
  const firstPanelSection = ref<any>();
136
253
  const isButtonLoading = ref<boolean>(false);
137
254
  const answerToAll = ref<boolean>(false);
138
255
  const firstPanel = ref<boolean>(false);
139
256
  const secondPanel = ref<boolean>(false);
257
+ const filterType = ref<'Да' | 'Нет' | null>(null);
258
+ const filterItems = [
259
+ { title: 'Все', value: null },
260
+ { title: 'Только «Да»', value: 'Да' },
261
+ { title: 'Только «Нет»', value: 'Нет' },
262
+ ];
140
263
  const surveyType = ref<'health' | 'critical'>('tab' in route.query && route.query.tab === 'criticalBase' ? 'critical' : 'health');
141
264
  const whichSurvey = computed(() =>
142
265
  surveyType.value === 'health'
@@ -144,17 +267,19 @@ export default defineComponent({
144
267
  ? 'surveyByHealthBase'
145
268
  : 'surveyByHealthBasePolicyholder'
146
269
  : whichMember.value === 'insured'
147
- ? 'surveyByCriticalBase'
148
- : 'surveyByCriticalBasePolicyholder',
270
+ ? 'surveyByCriticalBase'
271
+ : 'surveyByCriticalBasePolicyholder',
149
272
  );
150
273
  const firstQuestionList = ref<AnketaBody[]>([]);
151
- const secondQuestionList = ref<AnketaSecond[]>([]);
152
274
  const currentQuestion = ref<AnketaBody>();
153
275
  const currentSecond = ref<AnketaSecond>();
154
276
  const isPanelLoading = ref<boolean>(false);
155
277
  const searchQuery = ref<string>('');
278
+ const isFirstPanelOnRight = dataStore.isUnderwriter() && !useEnv().isProduction;
156
279
 
157
280
  const whichMember = computed(() => ('member' in route.query && !!route.query.member ? (route.query.member as 'insured' | 'policyholder') : 'insured'));
281
+ const isSecondRequired = computed(() => dataStore.controls.isSecondAnketaRequired);
282
+ const firstQuestions = computed(() => (filterType.value !== null ? firstQuestionList.value.filter(i => i.first.answerName === filterType.value) : firstQuestionList.value));
158
283
  const scrollForm = (direction: 'up' | 'down') => {
159
284
  const scrollObject = { top: direction === 'up' ? 0 : screen.height * 10, behavior: 'smooth' };
160
285
  if (firstPanel.value) {
@@ -168,16 +293,45 @@ export default defineComponent({
168
293
  await vForm.value.validate().then(async (v: { valid: Boolean; errors: any }) => {
169
294
  if (v.valid) {
170
295
  isButtonLoading.value = true;
171
- formStore[whichSurvey.value]!.body.forEach((survey: AnketaBody) => {
172
- if (survey.first.answerText === 'Нет') {
173
- survey.second = [];
174
- }
175
- });
296
+ const isValid = dataStore.validateAnketa(whichSurvey.value);
297
+ if (!isValid) {
298
+ isButtonLoading.value = false;
299
+ return false;
300
+ }
301
+ if (formStore[whichSurvey.value] && formStore[whichSurvey.value]?.body) {
302
+ formStore[whichSurvey.value]?.body.forEach(question => {
303
+ if (question.first.definedAnswers === 'Y' && question.first.answerName?.match(new RegExp('Да', 'i')) && question.second && question.second.length) {
304
+ question.second.forEach(second => {
305
+ if (second.answerType === 'D') second.answerText = formatDate(String(second.answerText))!.toISOString();
306
+ });
307
+ }
308
+ if (question.first.definedAnswers === 'Y' && question.first.answerName?.match(new RegExp('Нет', 'i')) && question.second && question.second.length) {
309
+ question.second.forEach(second => {
310
+ if (second.definedAnswers === 'N') {
311
+ second.answerText = null;
312
+ } else {
313
+ second.answerId = null;
314
+ second.answerName = null;
315
+ }
316
+ });
317
+ }
318
+ if (question.first.definedAnswers === 'D' && question.first.answerName?.match(new RegExp('Нет', 'i')) && question.first.answerText) {
319
+ question.first.answerText = null;
320
+ }
321
+ });
322
+ }
176
323
  formStore[whichSurvey.value]!.type = surveyType.value;
177
324
  const anketaToken = await dataStore.setSurvey(formStore[whichSurvey.value]!);
178
325
  if (typeof anketaToken === 'string') {
179
326
  formStore[whichSurvey.value]!.id = anketaToken;
180
327
  }
328
+ await dataStore.getQuestionList(
329
+ surveyType.value,
330
+ formStore.applicationData.processInstanceId,
331
+ whichMember.value === 'insured' ? formStore.applicationData.insuredApp[0].id : formStore.applicationData.clientApp.id,
332
+ whichSurvey.value,
333
+ whichMember.value,
334
+ );
181
335
  isButtonLoading.value = false;
182
336
  } else {
183
337
  const errors = document.querySelector('.v-input--error');
@@ -201,13 +355,40 @@ export default defineComponent({
201
355
  });
202
356
  };
203
357
 
204
- const openFirstPanel = async (question: AnketaBody) => {
205
- currentQuestion.value = question;
206
- formStore[whichSurvey.value]!.body.forEach((question_object: AnketaBody) => {
207
- if ((question_object.first.id === question.first.id && question_object.second && !question_object.second.length) || question_object.second == null) {
208
- question_object.second = JSON.parse(JSON.stringify(formStore[surveyType.value === 'health' ? 'surveyByHealthSecond' : 'surveyByCriticalSecond']));
358
+ const submitSecondaryForm = async () => {
359
+ await vSecondaryForm.value.validate().then(async (v: { valid: Boolean; errors: any }) => {
360
+ if (v.valid) {
361
+ if (isSecondRequired.value && currentQuestion.value && currentQuestion.value.second) {
362
+ const hasError = currentQuestion.value.second.find(second => (second.definedAnswers === 'N' ? !second.answerText : !second.answerName));
363
+ if (hasError) {
364
+ dataStore.showToaster('error', dataStore.t('toaster.emptySecondAnketa', { text: hasError.name }), 5000);
365
+ return false;
366
+ }
367
+ }
368
+ firstPanel.value = false;
369
+ secondPanel.value = false;
370
+ } else {
371
+ const errors = document.querySelector('.v-input--error');
372
+ if (errors) {
373
+ const errorText = errors.parentElement?.children[0].innerHTML;
374
+ if (errorText) {
375
+ dataStore.showToaster('error', dataStore.t('toaster.errorFormField', { text: errorText?.replace(/[-<>!//.]/g, '') }));
376
+ }
377
+ errors.scrollIntoView({
378
+ behavior: 'smooth',
379
+ block: 'center',
380
+ inline: 'nearest',
381
+ });
382
+ }
209
383
  }
210
384
  });
385
+ };
386
+ const openFirstPanel = async (question: AnketaBody) => {
387
+ currentQuestion.value = question;
388
+ if (isFirstPanelOnRight) {
389
+ dataStore.rightPanel.open = true;
390
+ dataStore.rightPanel.title = `${String(question.first.name).substring(0, 60)}...`;
391
+ }
211
392
  firstPanel.value = true;
212
393
  secondPanel.value = false;
213
394
  };
@@ -219,8 +400,8 @@ export default defineComponent({
219
400
  await dataStore.getQuestionRefs(question.id);
220
401
  secondPanel.value = true;
221
402
  dataStore.panelAction = null;
222
- dataStore.panel.open = true;
223
- dataStore.panel.title = question.name;
403
+ dataStore.rightPanel.open = true;
404
+ dataStore.rightPanel.title = question.name;
224
405
  isPanelLoading.value = false;
225
406
  };
226
407
 
@@ -231,12 +412,11 @@ export default defineComponent({
231
412
  }
232
413
  secondPanel.value = false;
233
414
  dataStore.panelAction = null;
234
- dataStore.panel.open = false;
415
+ dataStore.rightPanel.open = false;
235
416
  dataStore.questionRefs = [];
236
417
  };
237
418
 
238
419
  const getDefinedAnswerId = async (id: string, value: any, index: number) => {
239
- // @ts-ignore
240
420
  await dataStore.definedAnswers(id, whichSurvey.value, value, index);
241
421
  };
242
422
 
@@ -272,18 +452,16 @@ export default defineComponent({
272
452
  formStore.applicationData.processInstanceId,
273
453
  whichMember.value === 'insured' ? formStore.applicationData.insuredApp[0].id : formStore.applicationData.clientApp.id,
274
454
  whichSurvey.value,
275
- surveyType.value === 'health' ? 'surveyByHealthSecond' : 'surveyByCriticalSecond',
276
455
  whichMember.value,
277
456
  );
278
457
  firstQuestionList.value = formStore[whichSurvey.value]!.body;
279
- secondQuestionList.value = formStore[surveyType.value === 'health' ? 'surveyByHealthSecond' : 'surveyByCriticalSecond']!;
280
458
  formStore[whichSurvey.value]!.type = surveyType.value;
281
459
  const negativeAnswer = firstQuestionList.value.every(i => i.first.answerName === 'Нет');
282
460
  if (negativeAnswer) {
283
461
  answerToAll.value = true;
284
462
  }
285
463
  await Promise.allSettled(
286
- firstQuestionList.value.map(async (question: any) => {
464
+ firstQuestionList.value.map(async question => {
287
465
  await dataStore.definedAnswers(question.first.id, whichSurvey.value);
288
466
  }),
289
467
  );
@@ -293,10 +471,14 @@ export default defineComponent({
293
471
  await onInit();
294
472
  });
295
473
 
474
+ onUnmounted(() => {
475
+ dataStore.abortRequests();
476
+ });
477
+
296
478
  watch(
297
- () => dataStore.panel.open,
479
+ () => dataStore.rightPanel.open,
298
480
  () => {
299
- if (dataStore.panel.open === false) {
481
+ if (dataStore.rightPanel.open === false) {
300
482
  secondPanel.value = false;
301
483
  dataStore.panelAction = null;
302
484
  }
@@ -308,7 +490,7 @@ export default defineComponent({
308
490
  () => firstQuestionList.value,
309
491
  value => {
310
492
  if (value) {
311
- const hasPositiveAnswer = value.some(i => i.first.definedAnswers === 'Y' && i.first.answerName !== 'Нет');
493
+ const hasPositiveAnswer = value.some(i => (i.first.definedAnswers === 'Y' || i.first.definedAnswers === 'D') && i.first.answerName !== 'Нет');
312
494
  answerToAll.value = !hasPositiveAnswer;
313
495
  }
314
496
  },
@@ -320,22 +502,30 @@ export default defineComponent({
320
502
  return {
321
503
  // State
322
504
  vForm,
505
+ vSecondaryForm,
323
506
  formStore,
324
507
  answerToAll,
508
+ firstQuestions,
325
509
  firstQuestionList,
326
- secondQuestionList,
327
510
  whichSurvey,
328
511
  isButtonLoading,
329
512
  firstPanel,
513
+ filterType,
514
+ filterItems,
330
515
  secondPanel,
331
516
  currentQuestion,
332
517
  currentSecond,
333
518
  isPanelLoading,
334
519
  searchQuery,
335
520
  firstPanelSection,
521
+ isSecondRequired,
522
+
523
+ // Computed
524
+ isFirstPanelOnRight,
336
525
 
337
526
  // Functions
338
527
  submitForm,
528
+ submitSecondaryForm,
339
529
  getDefinedAnswerId,
340
530
  scrollForm,
341
531
  handleToggler,