hl-core 0.0.9-beta.4 → 0.0.9-beta.41

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 (61) hide show
  1. package/api/base.api.ts +904 -0
  2. package/api/index.ts +2 -620
  3. package/api/interceptors.ts +58 -14
  4. package/components/Button/Btn.vue +2 -2
  5. package/components/Complex/MessageBlock.vue +2 -2
  6. package/components/Complex/Page.vue +1 -1
  7. package/components/Dialog/Dialog.vue +60 -15
  8. package/components/Form/DynamicForm.vue +100 -0
  9. package/components/Form/FormBlock.vue +12 -3
  10. package/components/Form/FormData.vue +114 -0
  11. package/components/Form/FormToggle.vue +9 -3
  12. package/components/Form/ManagerAttachment.vue +150 -86
  13. package/components/Form/ProductConditionsBlock.vue +59 -6
  14. package/components/Input/Datepicker.vue +1 -8
  15. package/components/Input/DynamicInput.vue +23 -0
  16. package/components/Input/FileInput.vue +16 -4
  17. package/components/Input/FormInput.vue +1 -3
  18. package/components/Input/Monthpicker.vue +34 -0
  19. package/components/Input/PanelInput.vue +5 -1
  20. package/components/Input/RoundedEmptyField.vue +5 -0
  21. package/components/Input/RoundedSelect.vue +13 -0
  22. package/components/Input/SwitchInput.vue +64 -0
  23. package/components/Input/TextInput.vue +159 -0
  24. package/components/Layout/Drawer.vue +17 -4
  25. package/components/Layout/Header.vue +23 -2
  26. package/components/Layout/SettingsPanel.vue +13 -7
  27. package/components/Menu/InfoMenu.vue +35 -0
  28. package/components/Menu/MenuNav.vue +17 -2
  29. package/components/Pages/Anketa.vue +140 -52
  30. package/components/Pages/Auth.vue +12 -1
  31. package/components/Pages/ContragentForm.vue +129 -50
  32. package/components/Pages/Documents.vue +72 -7
  33. package/components/Pages/InvoiceInfo.vue +1 -1
  34. package/components/Pages/MemberForm.vue +269 -96
  35. package/components/Pages/ProductAgreement.vue +1 -8
  36. package/components/Pages/ProductConditions.vue +798 -168
  37. package/components/Panel/PanelHandler.vue +373 -45
  38. package/components/Panel/PanelSelectItem.vue +17 -2
  39. package/components/Panel/RightPanelCloser.vue +7 -0
  40. package/components/Transitions/Animation.vue +28 -0
  41. package/composables/axios.ts +2 -1
  42. package/composables/classes.ts +415 -8
  43. package/composables/constants.ts +65 -2
  44. package/composables/fields.ts +291 -0
  45. package/composables/index.ts +58 -5
  46. package/composables/styles.ts +22 -10
  47. package/layouts/default.vue +48 -3
  48. package/locales/ru.json +460 -12
  49. package/nuxt.config.ts +1 -1
  50. package/package.json +25 -22
  51. package/pages/Token.vue +1 -12
  52. package/plugins/helperFunctionsPlugins.ts +0 -3
  53. package/plugins/vuetifyPlugin.ts +2 -0
  54. package/store/data.store.ts +1031 -224
  55. package/store/extractStore.ts +17 -0
  56. package/store/form.store.ts +13 -1
  57. package/store/member.store.ts +1 -1
  58. package/store/rules.ts +53 -5
  59. package/types/enum.ts +37 -0
  60. package/types/form.ts +94 -0
  61. package/types/index.ts +216 -20
@@ -1,6 +1,6 @@
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 && !firstPanel && !secondPanel" class="flex flex-col shrink grow max-h-[90vh]">
4
4
  <section :class="[$styles.blueBgLight, $styles.rounded]" class="mx-[10px] my-[14px] p-4 flex flex-col gap-4">
5
5
  <base-form-toggle
6
6
  v-model="answerToAll"
@@ -10,7 +10,7 @@
10
10
  @clicked="handleToggler"
11
11
  />
12
12
  </section>
13
- <v-form ref="vForm" class="max-h-[70vh] overflow-y-scroll" @submit="submitForm">
13
+ <v-form ref="vForm" class="grow shrink overflow-y-scroll" @submit="submitForm">
14
14
  <section
15
15
  v-if="firstQuestionList.filter(i => i.first.definedAnswers === 'N').length"
16
16
  :class="[$styles.blueBgLight, $styles.rounded]"
@@ -34,19 +34,19 @@
34
34
  <base-form-text-section v-for="(question, index) in firstQuestionList.filter(i => i.first.definedAnswers === 'Y')" :key="index">
35
35
  <base-fade-transition>
36
36
  <div
37
- v-if="question.first.answerName === 'Да' && secondQuestionList"
37
+ v-if="question.first.answerName === 'Да' && question.second"
38
38
  :class="[$styles.greenBg, $styles.whiteText, $styles.textSimple]"
39
39
  class="rounded-t-lg pl-6 py-1 cursor-pointer"
40
40
  @click="openFirstPanel(question)"
41
41
  >
42
- {{ $dataStore.t('questionnaireType.pleaseAnswer', { text: secondQuestionList.length }) }}
42
+ {{ $dataStore.t('questionnaireType.pleaseAnswer', { text: question.second.length }) }}
43
43
  </div>
44
44
  </base-fade-transition>
45
45
  <span :class="[$styles.textTitle]" class="border-b-[1px] border-b-[#F3F6FC] p-6 flex items-center justify-between">
46
46
  {{ question.first.name }}
47
47
  <base-fade-transition>
48
48
  <i
49
- v-if="question.first.answerName === 'Да' && secondQuestionList && secondQuestionList.length"
49
+ v-if="question.first.answerName === 'Да' && question.second && question.second.length"
50
50
  class="mdi mdi-chevron-right text-2xl cursor-pointer"
51
51
  @click="openFirstPanel(question)"
52
52
  ></i>
@@ -68,43 +68,87 @@
68
68
  </div>
69
69
  </base-form-text-section>
70
70
  </section>
71
+ <section
72
+ v-if="firstQuestionList.filter(i => i.first.definedAnswers === 'D').length"
73
+ :class="[$styles.blueBgLight, $styles.rounded]"
74
+ class="mx-[10px] mt-[14px] p-4 flex flex-col gap-4"
75
+ >
76
+ <base-form-text-section v-for="(question, index) in firstQuestionList.filter(i => i.first.definedAnswers === 'D')" :key="index">
77
+ <span :class="[$styles.textTitle]" class="border-b-[1px] border-b-[#F3F6FC] p-6 flex items-center justify-between"> {{ question.first.name }} </span>
78
+ <div class="flex items-center justify-start gap-5 px-4 pt-4" :class="[$styles.textSimple]">
79
+ <v-radio-group
80
+ v-model="question.first.answerName"
81
+ class="anketa-radio"
82
+ :true-icon="`mdi-radiobox-marked ${$styles.greenText}`"
83
+ false-icon="mdi-radiobox-blank text-[#636363]"
84
+ :rules="$rules.required"
85
+ :readonly="formStore.isDisabled[whichSurvey] || !$dataStore.isTask()"
86
+ inline
87
+ >
88
+ <v-radio label="Да" value="Да" />
89
+ <v-radio label="Нет" value="Нет" />
90
+ </v-radio-group>
91
+ </div>
92
+ <base-fade-transition>
93
+ <div v-if="question.first.answerName === 'Да'" :class="[$styles.whiteText, $styles.textSimple]">
94
+ <base-form-input
95
+ v-model="question.first.answerText"
96
+ :label="$dataStore.t('labels.inDetails')"
97
+ :readonly="formStore.isDisabled[whichSurvey] || !$dataStore.isTask()"
98
+ :rules="$rules.required"
99
+ />
100
+ </div>
101
+ </base-fade-transition>
102
+ </base-form-text-section>
103
+ </section>
71
104
  </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
- />
105
+ <div class="px-[14px]">
106
+ <base-btn
107
+ class="my-[14px] self-center"
108
+ :loading="isButtonLoading"
109
+ :disabled="formStore.isDisabled[whichSurvey] || !$dataStore.isTask()"
110
+ @click="submitForm"
111
+ :text="$dataStore.t('buttons.save')"
112
+ />
113
+ </div>
79
114
  </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
- "
115
+ <base-btn
116
+ v-if="currentQuestion && currentQuestion.second && currentQuestion.second.length && firstPanel"
117
+ class="!absolute z-10 my-[14px] self-center w-[96%] bottom-[-40px]"
118
+ :text="$dataStore.t('buttons.save')"
119
+ @click="submitSecondaryForm"
88
120
  />
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">
121
+ <section ref="firstPanelSection" v-if="currentQuestion && currentQuestion.second && firstPanel" class="flex flex-col px-[10px] pb-[14px]" :class="[$styles.scrollPage]">
122
+ <v-form
123
+ v-if="currentQuestion"
124
+ :class="[$styles.blueBgLight, $styles.rounded]"
125
+ class="mx-[10px] mt-[14px] p-4 flex flex-col gap-4"
126
+ ref="vSecondaryForm"
127
+ @submit="submitSecondaryForm"
128
+ >
91
129
  <base-form-text-section v-for="question in currentQuestion.second" :title="question.name" :key="question.name">
92
130
  <base-form-input
93
131
  v-if="question.definedAnswers === 'N'"
94
132
  v-model="question.answerText"
95
133
  class="border-t-[1px] border-t-[#F3F6FC]"
96
- placeholder="Введите текст"
134
+ :placeholder="$dataStore.t('labels.inputText')"
97
135
  :readonly="formStore.isDisabled[whichSurvey] || !$dataStore.isTask()"
136
+ :rules="isSecondRequired ? $rules.required : []"
98
137
  />
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>
138
+ <base-panel-input
139
+ v-else
140
+ :class="[$styles.textTitle, $styles.greenText]"
141
+ :value="question.answerName ? question.answerName : 'Выбрать вариант ответа'"
142
+ :readonly="formStore.isDisabled[whichSurvey] || !$dataStore.isTask()"
143
+ :clearable="false"
144
+ :error-messages="isSecondRequired ? (question.answerName ? [] : ['Выбрать вариант ответа']) : []"
145
+ @click="openSecondPanel(question)"
146
+ ></base-panel-input>
103
147
  </base-form-text-section>
104
- </section>
148
+ </v-form>
105
149
  </section>
106
150
  </base-fade-transition>
107
- <Teleport v-if="secondPanel" to="#panel-actions">
151
+ <Teleport v-if="secondPanel" to="#right-panel-actions">
108
152
  <div :class="[$styles.scrollPage]" class="flex flex-col items-center">
109
153
  <base-rounded-input v-model="searchQuery" :label="$dataStore.t('labels.search')" class="w-full p-2" :hide-details="true" />
110
154
  <div v-if="$dataStore.questionRefs && $dataStore.questionRefs.length && isPanelLoading === false" class="w-full flex flex-col gap-2 p-2">
@@ -119,7 +163,7 @@
119
163
  <base-loader v-if="isPanelLoading" class="absolute mt-10" :size="50" />
120
164
  </div>
121
165
  </Teleport>
122
- <base-scroll-buttons @up="scrollForm('up')" @down="scrollForm('down')" />
166
+ <base-scroll-buttons v-if="firstQuestionList && firstQuestionList.length" @up="scrollForm('up')" @down="scrollForm('down')" />
123
167
  </template>
124
168
 
125
169
  <script lang="ts">
@@ -132,6 +176,7 @@ export default defineComponent({
132
176
  const formStore = useFormStore();
133
177
  const dataStore = useDataStore();
134
178
  const vForm = ref<any>();
179
+ const vSecondaryForm = ref<any>();
135
180
  const firstPanelSection = ref<any>();
136
181
  const isButtonLoading = ref<boolean>(false);
137
182
  const answerToAll = ref<boolean>(false);
@@ -148,13 +193,13 @@ export default defineComponent({
148
193
  : 'surveyByCriticalBasePolicyholder',
149
194
  );
150
195
  const firstQuestionList = ref<AnketaBody[]>([]);
151
- const secondQuestionList = ref<AnketaSecond[]>([]);
152
196
  const currentQuestion = ref<AnketaBody>();
153
197
  const currentSecond = ref<AnketaSecond>();
154
198
  const isPanelLoading = ref<boolean>(false);
155
199
  const searchQuery = ref<string>('');
156
200
 
157
201
  const whichMember = computed(() => ('member' in route.query && !!route.query.member ? (route.query.member as 'insured' | 'policyholder') : 'insured'));
202
+ const isSecondRequired = computed(() => dataStore.controls.isSecondAnketaRequired);
158
203
  const scrollForm = (direction: 'up' | 'down') => {
159
204
  const scrollObject = { top: direction === 'up' ? 0 : screen.height * 10, behavior: 'smooth' };
160
205
  if (firstPanel.value) {
@@ -168,11 +213,28 @@ export default defineComponent({
168
213
  await vForm.value.validate().then(async (v: { valid: Boolean; errors: any }) => {
169
214
  if (v.valid) {
170
215
  isButtonLoading.value = true;
171
- formStore[whichSurvey.value]!.body.forEach((survey: AnketaBody) => {
172
- if (survey.first.answerText === 'Нет') {
173
- survey.second = [];
174
- }
175
- });
216
+ const isValid = dataStore.validateAnketa(whichSurvey.value);
217
+ if (!isValid) {
218
+ isButtonLoading.value = false;
219
+ return false;
220
+ }
221
+ if (formStore[whichSurvey.value] && formStore[whichSurvey.value]?.body) {
222
+ formStore[whichSurvey.value]?.body.forEach(question => {
223
+ if (question.first.definedAnswers === 'Y' && question.first.answerName?.match(new RegExp('Нет', 'i')) && question.second && question.second.length) {
224
+ question.second.forEach(second => {
225
+ if (second.definedAnswers === 'N') {
226
+ second.answerText = null;
227
+ } else {
228
+ second.answerId = null;
229
+ second.answerName = null;
230
+ }
231
+ });
232
+ }
233
+ if (question.first.definedAnswers === 'D' && question.first.answerName?.match(new RegExp('Нет', 'i')) && question.first.answerText) {
234
+ question.first.answerText = null;
235
+ }
236
+ });
237
+ }
176
238
  formStore[whichSurvey.value]!.type = surveyType.value;
177
239
  const anketaToken = await dataStore.setSurvey(formStore[whichSurvey.value]!);
178
240
  if (typeof anketaToken === 'string') {
@@ -201,13 +263,36 @@ export default defineComponent({
201
263
  });
202
264
  };
203
265
 
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']));
266
+ const submitSecondaryForm = async () => {
267
+ await vSecondaryForm.value.validate().then(async (v: { valid: Boolean; errors: any }) => {
268
+ if (v.valid) {
269
+ if (isSecondRequired.value && currentQuestion.value && currentQuestion.value.second) {
270
+ const hasError = currentQuestion.value.second.find(second => (second.definedAnswers === 'N' ? !second.answerText : !second.answerName));
271
+ if (hasError) {
272
+ dataStore.showToaster('error', dataStore.t('toaster.emptySecondAnketa', { text: hasError.name }), 5000);
273
+ return false;
274
+ }
275
+ }
276
+ firstPanel.value = false;
277
+ secondPanel.value = false;
278
+ } else {
279
+ const errors = document.querySelector('.v-input--error');
280
+ if (errors) {
281
+ const errorText = errors.parentElement?.children[0].innerHTML;
282
+ if (errorText) {
283
+ dataStore.showToaster('error', dataStore.t('toaster.errorFormField', { text: errorText?.replace(/[-<>!//.]/g, '') }));
284
+ }
285
+ errors.scrollIntoView({
286
+ behavior: 'smooth',
287
+ block: 'center',
288
+ inline: 'nearest',
289
+ });
290
+ }
209
291
  }
210
292
  });
293
+ };
294
+ const openFirstPanel = async (question: AnketaBody) => {
295
+ currentQuestion.value = question;
211
296
  firstPanel.value = true;
212
297
  secondPanel.value = false;
213
298
  };
@@ -219,8 +304,8 @@ export default defineComponent({
219
304
  await dataStore.getQuestionRefs(question.id);
220
305
  secondPanel.value = true;
221
306
  dataStore.panelAction = null;
222
- dataStore.panel.open = true;
223
- dataStore.panel.title = question.name;
307
+ dataStore.rightPanel.open = true;
308
+ dataStore.rightPanel.title = question.name;
224
309
  isPanelLoading.value = false;
225
310
  };
226
311
 
@@ -231,12 +316,11 @@ export default defineComponent({
231
316
  }
232
317
  secondPanel.value = false;
233
318
  dataStore.panelAction = null;
234
- dataStore.panel.open = false;
319
+ dataStore.rightPanel.open = false;
235
320
  dataStore.questionRefs = [];
236
321
  };
237
322
 
238
323
  const getDefinedAnswerId = async (id: string, value: any, index: number) => {
239
- // @ts-ignore
240
324
  await dataStore.definedAnswers(id, whichSurvey.value, value, index);
241
325
  };
242
326
 
@@ -272,18 +356,16 @@ export default defineComponent({
272
356
  formStore.applicationData.processInstanceId,
273
357
  whichMember.value === 'insured' ? formStore.applicationData.insuredApp[0].id : formStore.applicationData.clientApp.id,
274
358
  whichSurvey.value,
275
- surveyType.value === 'health' ? 'surveyByHealthSecond' : 'surveyByCriticalSecond',
276
359
  whichMember.value,
277
360
  );
278
361
  firstQuestionList.value = formStore[whichSurvey.value]!.body;
279
- secondQuestionList.value = formStore[surveyType.value === 'health' ? 'surveyByHealthSecond' : 'surveyByCriticalSecond']!;
280
362
  formStore[whichSurvey.value]!.type = surveyType.value;
281
363
  const negativeAnswer = firstQuestionList.value.every(i => i.first.answerName === 'Нет');
282
364
  if (negativeAnswer) {
283
365
  answerToAll.value = true;
284
366
  }
285
367
  await Promise.allSettled(
286
- firstQuestionList.value.map(async (question: any) => {
368
+ firstQuestionList.value.map(async question => {
287
369
  await dataStore.definedAnswers(question.first.id, whichSurvey.value);
288
370
  }),
289
371
  );
@@ -293,10 +375,14 @@ export default defineComponent({
293
375
  await onInit();
294
376
  });
295
377
 
378
+ onUnmounted(() => {
379
+ dataStore.abortRequests();
380
+ });
381
+
296
382
  watch(
297
- () => dataStore.panel.open,
383
+ () => dataStore.rightPanel.open,
298
384
  () => {
299
- if (dataStore.panel.open === false) {
385
+ if (dataStore.rightPanel.open === false) {
300
386
  secondPanel.value = false;
301
387
  dataStore.panelAction = null;
302
388
  }
@@ -308,7 +394,7 @@ export default defineComponent({
308
394
  () => firstQuestionList.value,
309
395
  value => {
310
396
  if (value) {
311
- const hasPositiveAnswer = value.some(i => i.first.definedAnswers === 'Y' && i.first.answerName !== 'Нет');
397
+ const hasPositiveAnswer = value.some(i => (i.first.definedAnswers === 'Y' || i.first.definedAnswers === 'D') && i.first.answerName !== 'Нет');
312
398
  answerToAll.value = !hasPositiveAnswer;
313
399
  }
314
400
  },
@@ -320,10 +406,10 @@ export default defineComponent({
320
406
  return {
321
407
  // State
322
408
  vForm,
409
+ vSecondaryForm,
323
410
  formStore,
324
411
  answerToAll,
325
412
  firstQuestionList,
326
- secondQuestionList,
327
413
  whichSurvey,
328
414
  isButtonLoading,
329
415
  firstPanel,
@@ -333,9 +419,11 @@ export default defineComponent({
333
419
  isPanelLoading,
334
420
  searchQuery,
335
421
  firstPanelSection,
422
+ isSecondRequired,
336
423
 
337
424
  // Functions
338
425
  submitForm,
426
+ submitSecondaryForm,
339
427
  getDefinedAnswerId,
340
428
  scrollForm,
341
429
  handleToggler,
@@ -24,7 +24,15 @@
24
24
  <span :class="[$styles.greyTextDark]" class="text-[16px]">{{ $dataStore.t('labels.needAuth') }}</span>
25
25
  </div>
26
26
  <v-form ref="vForm" class="w-2/3 lg:w-[25vw] self-center">
27
- <base-rounded-input class="mb-1" v-model.trim="login" :rules="$rules.required" :loading="authLoading" :placeholder="$dataStore.t('buttons.userLogin')" type="text" />
27
+ <base-rounded-input
28
+ class="mb-1"
29
+ v-model.trim="login"
30
+ :rules="$rules.required"
31
+ :loading="authLoading"
32
+ :placeholder="$dataStore.t('buttons.userLogin')"
33
+ type="text"
34
+ @keyup.enter="submitAuthForm"
35
+ />
28
36
  <base-rounded-input
29
37
  class="mb-1"
30
38
  v-model.trim="password"
@@ -34,6 +42,7 @@
34
42
  :append-inner-icon="showPassword ? 'mdi-eye-outline' : 'mdi-eye-off-outline'"
35
43
  @append="showPassword = !showPassword"
36
44
  :type="showPassword ? ('' as InputTypes) : 'password'"
45
+ @keyup.enter="submitAuthForm"
37
46
  />
38
47
  <span v-if="$dataStore.isLKA" class="inline-block w-full text-end mb-4" :class="[$styles.textSimple, $styles.greyTextDark]" @click="isLogin = false">{{
39
48
  $dataStore.t('labels.resetPassword')
@@ -61,6 +70,7 @@
61
70
  :loading="authLoading"
62
71
  :placeholder="$dataStore.t('form.phoneNumber')"
63
72
  type="text"
73
+ @keyup.enter="submitAuthForm"
64
74
  />
65
75
  <base-rounded-input
66
76
  v-if="resetPasswordType === 'email'"
@@ -69,6 +79,7 @@
69
79
  :loading="authLoading"
70
80
  :placeholder="$dataStore.t('form.email')"
71
81
  type="text"
82
+ @keyup.enter="submitAuthForm"
72
83
  />
73
84
  <span class="inline-block w-full text-end mb-4" :class="[$styles.textSimple, $styles.greyTextDark]" @click="isLogin = true">{{ $dataStore.t('buttons.login') }}</span>
74
85
  <base-btn :text="$dataStore.t('buttons.reset')" :disabled="authLoading" :btn="$styles.greenBtn" @click="submitAuthForm" />