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
@@ -17,50 +17,87 @@
17
17
  >{{ `Запрашиваемая страховая сумма: ` }} <b>{{ `${requestedSumInsured}₸` }}</b>
18
18
  </span>
19
19
  </base-content-block>
20
+ <base-content-block v-if="$dataStore.isLifetrip" class="flex flex-col gap-3">
21
+ <span
22
+ >{{ `Стоимость на страховую сумму ${insuredAmount}:` }} <b>{{ `${price}₸` }}</b></span
23
+ >
24
+ </base-content-block>
20
25
  <base-btn :text="$dataStore.t('confirm.yes')" @click="handleTask" />
21
26
  <base-btn :btn="$styles.blueLightBtn" :text="$dataStore.t('confirm.no')" @click="closePanel" />
22
27
  </div>
23
28
  </section>
24
- <section v-if="signingActions" class="relative">
25
- <div>
26
- <base-fade-transition>
27
- <div v-if="!isSendNumberOpen" :class="[$styles.flexColNav]">
28
- <div :class="[$styles.blueBgLight]" class="rounded-lg p-4">
29
- <v-expansion-panels v-if="formStore.signUrls && formStore.signUrls.length" variant="accordion" multiple>
30
- <v-expansion-panel v-for="signUrl of formStore.signUrls" :key="signUrl.iin!" class="border-[1px]" elevation="0" bg-color="#FFF">
31
- <v-expansion-panel-title class="h-[80px]" :class="$styles.textTitle">{{ `${signUrl.longName} - ${signUrl.iin}` }}</v-expansion-panel-title>
32
- <v-expansion-panel-text class="border-t-[1px]">
33
- <section class="flex flex-col gap-4 py-3" :class="$styles.textSimple">
34
- <base-btn :loading="loading" :text="$dataStore.t('sign.copyCloud')" @click="$dataStore.copyToClipboard(signUrl.uri)" />
35
- <base-btn :loading="loading" :btn="$styles.blueLightBtn" :text="$dataStore.t('sign.recipientNumber')" @click="openSmsPanel(signUrl)" />
36
- </section>
37
- </v-expansion-panel-text>
38
- </v-expansion-panel>
39
- </v-expansion-panels>
40
- <base-list-empty v-else />
41
- </div>
42
- </div>
43
- <div v-if="isSendNumberOpen" :class="[$styles.flexColNav]">
44
- <i
45
- class="mdi mdi-arrow-left cursor-pointer absolute text-xl left-0 top-0 rounded-br-full bg-white border-[1px] pb-3 pt-1 pl-1 pr-3"
46
- @click="isSendNumberOpen = false"
47
- ></i>
48
- <base-form-section :title="selectedClient && selectedClient.longName ? selectedClient.longName : ''">
49
- <v-form ref="vForm">
50
- <base-rounded-input
51
- v-model="phoneNumber"
52
- :maska="$maska.phone"
53
- :rules="$rules.required.concat($rules.phoneFormat)"
54
- :label="$dataStore.t('form.phoneNumber')"
55
- placeholder="+7 7"
56
- />
57
- </v-form>
58
- <base-btn :text="$dataStore.t('buttons.sendSMS')" :loading="loading" @click="submitForm"
59
- /></base-form-section>
29
+ <section v-if="chooseSignActions">
30
+ <div v-if="!isElectronicContract && !isPaperContract && !isScansDocuments && !isQr" :class="[$styles.flexColNav]">
31
+ <base-btn :text="$dataStore.t('buttons.sendOnPaper')" :disabled="isPaperDisabled" :loading="loading" @click="handleSignAction('paper')" />
32
+ <base-btn :text="$dataStore.t('buttons.sendElectronically')" :disabled="isElectronicDisabled" :loading="loading" @click="handleSignAction('electronic')" />
33
+ <base-btn :text="$dataStore.t('buttons.generatePrintedForms')" :disabled="isScansDisabled" :loading="loading" @click="handleSignAction('scans')" />
34
+ <base-btn :text="$dataStore.t('buttons.sendEgovMob')" :disabled="isQrDisabled" :loading="loading" @click="handleSignAction('qr')" />
35
+ </div>
36
+ <div v-if="isPaperContract" :class="[$styles.flexColNav]">
37
+ <base-btn :text="$dataStore.t('buttons.downloadContract')" :loading="$dataStore.isButtonsLoading" @click="generateDocument" />
38
+ </div>
39
+ <div v-if="isScansDocuments" :class="[$styles.flexColNav]">
40
+ <base-btn :text="$dataStore.t('buttons.downloadStatement')" @click="downloadTemplate(constants.documentTypes.statement, 'docx')" />
41
+ <base-btn :text="$dataStore.t('buttons.downloadContract')" @click="downloadTemplate(constants.documentTypes.contract, 'doc')" />
42
+ <base-btn :text="$dataStore.t('buttons.downloadApplication')" @click="downloadTemplate(constants.documentTypes.application1, 'vnd.ms-excel')" />
43
+ <base-form-section class="mt-4 flex flex-col !gap-2" :title="$dataStore.t('clients.attachScansSignDocs')">
44
+ <base-file-input :label="$dataStore.t('labels.attachStatement')" @input.prevent="onFileChangeScans($event, 'statement')" @onClear="onClearFile('statement')" />
45
+ <base-file-input :label="$dataStore.t('labels.attachContract')" @input.prevent="onFileChangeScans($event, 'contract')" @onClear="onClearFile('contract')" />
46
+ <base-file-input :label="$dataStore.t('labels.attachApplication')" @input.prevent="onFileChangeScans($event, 'app')" @onClear="onClearFile('app')" />
47
+ <base-file-input :label="$dataStore.t('labels.attachPowerOfAttorney')" @input.prevent="onFileChangeScans($event, 'attorney')" @onClear="onClearFile('attorney')" />
48
+ </base-form-section>
49
+ <base-btn :text="$dataStore.t('buttons.sign')" :loading="$dataStore.isButtonsLoading" @click="sendFiles" />
50
+ <base-btn :text="$dataStore.t('buttons.cancel')" :btn="$styles.whiteBtn" @click="isScansDocuments = false" />
51
+ </div>
52
+ <div v-if="isQr" :class="[$styles.flexColNav]">
53
+ <base-form-section :title="''">
54
+ <base-loader v-if="isQrLoading" class="self-center m-5 opacity-70" />
55
+ <div v-if="qrUrl && !isQrLoading">
56
+ <img width="135" height="135" class="ma-auto" :src="qrUrl" alt="" />
57
+ <span :class="[$styles.textSimple]" class="mt-3 text-center d-block">{{ $dataStore.t('sign.scanQrCode') }}</span>
60
58
  </div>
61
- </base-fade-transition>
59
+ <base-btn class="mt-10" :loading="loading" :text="$dataStore.t('sign.copyEgov')" @click="$dataStore.copyToClipboard(urlCopy)" />
60
+ <base-btn :text="$dataStore.t('buttons.cancel')" :btn="$styles.whiteBtn" @click="closeQrPanel" />
61
+ </base-form-section>
62
62
  </div>
63
63
  </section>
64
+ <section v-if="signingActions" class="relative">
65
+ <base-fade-transition>
66
+ <div v-if="!isSendNumberOpen" :class="[$styles.flexColNav]">
67
+ <div :class="[$styles.blueBgLight]" class="rounded-lg p-4">
68
+ <v-expansion-panels v-if="formStore.signUrls && formStore.signUrls.length" variant="accordion" multiple>
69
+ <v-expansion-panel v-for="signUrl of formStore.signUrls" :key="signUrl.iin!" class="border-[1px]" elevation="0" bg-color="#FFF">
70
+ <v-expansion-panel-title class="h-[80px]" :class="$styles.textTitle">
71
+ {{ `${signUrl.longName} - ${signUrl.iin}` }}
72
+ </v-expansion-panel-title>
73
+ <v-expansion-panel-text class="border-t-[1px]">
74
+ <section class="flex flex-col gap-4 py-3" :class="$styles.textSimple">
75
+ <base-btn :loading="loading" :text="$dataStore.t('sign.copyCloud')" @click="$dataStore.copyToClipboard(signUrl.uri)" />
76
+ <base-btn :loading="loading" :btn="$styles.blueLightBtn" :text="$dataStore.t('sign.recipientNumber')" @click="openSmsPanel(signUrl)" />
77
+ </section>
78
+ </v-expansion-panel-text>
79
+ </v-expansion-panel>
80
+ </v-expansion-panels>
81
+ <base-list-empty v-else />
82
+ </div>
83
+ </div>
84
+ <div v-if="isSendNumberOpen" :class="[$styles.flexColNav]">
85
+ <i class="mdi mdi-arrow-left cursor-pointer absolute text-xl left-0 top-0 rounded-br-full bg-white border-[1px] pb-3 pt-1 pl-1 pr-3" @click="isSendNumberOpen = false"></i>
86
+ <base-form-section :title="selectedClient && selectedClient.longName ? selectedClient.longName : ''">
87
+ <v-form ref="vForm">
88
+ <base-rounded-input
89
+ v-model="phoneNumber"
90
+ :maska="$maska.phone"
91
+ :rules="$rules.required.concat($rules.phoneFormat)"
92
+ :label="$dataStore.t('form.phoneNumber')"
93
+ placeholder="+7 7"
94
+ />
95
+ </v-form>
96
+ <base-btn :text="$dataStore.t('buttons.sendSMS')" :loading="loading" @click="submitForm" />
97
+ </base-form-section>
98
+ </div>
99
+ </base-fade-transition>
100
+ </section>
64
101
  <section v-if="payingActions" class="relative">
65
102
  <div>
66
103
  <base-fade-transition>
@@ -99,27 +136,58 @@
99
136
  :maska="$maska.date"
100
137
  :rules="$rules.required"
101
138
  :label="$dataStore.t('form.date')"
102
- append-inner-icon="mdi mdi-calendar-blank-outline" />
139
+ append-inner-icon="mdi mdi-calendar-blank-outline"
140
+ />
103
141
  <base-file-input v-if="!affiliationDocument" @input.prevent="onFileChange($event)" />
104
142
  <base-empty-form-field v-if="affiliationDocument" class="justify-between">
105
143
  {{ `${affiliationDocument.fileTypeName} - ${affiliationDocument.fileName}` }}
106
- <i class="cursor-pointer mdi mdi-file-document mr-6 text-[#a0b3d8] text-xl"></i></base-empty-form-field
107
- ></base-content-block>
144
+ <i class="cursor-pointer mdi mdi-file-document mr-6 text-[#a0b3d8] text-xl"></i
145
+ ></base-empty-form-field>
146
+ </base-content-block>
108
147
  </v-form>
109
148
  <base-btn :text="buttonText" :loading="loading" @click="submitForm" />
110
149
  </div>
111
150
  </section>
151
+ <section v-if="templateAction">
152
+ <div :class="[$styles.flexColNav]">
153
+ <base-content-block>
154
+ <base-panel-item class="cursor-pointer bg-white mb-4 border-b-0 rounded" @click.prevent="downloadTemplate(constants.documentTypes.insuredsList, 'vnd.ms-excel')">
155
+ {{ $dataStore.t('downloadTemplate') }}
156
+ <i class="mdi mdi-download text-2xl text-[#A0B3D8]"></i
157
+ ></base-panel-item>
158
+ </base-content-block>
159
+ <base-content-block>
160
+ <v-form ref="vForm" class="mb-3">
161
+ <base-form-input v-model.trim="email" :label="$dataStore.t('form.email')" :rules="$rules.required" />
162
+ </v-form>
163
+ <base-btn :text="$dataStore.t('form.sendToEmail')" :loading="loading" @click="sendTemplateToEmail" />
164
+ </base-content-block>
165
+ </div>
166
+ </section>
112
167
  </template>
113
168
 
114
169
  <script lang="ts">
115
- import { DocumentItem } from '../../composables/classes';
170
+ import { DocumentItem, Value } from '../../composables/classes';
171
+ import { HubConnectionBuilder } from '@microsoft/signalr';
172
+
116
173
  export default defineComponent({
117
- setup() {
174
+ emits: ['task'],
175
+ setup(props, { emit }) {
118
176
  const route = useRoute();
119
177
  const dataStore = useDataStore();
120
178
  const formStore = useFormStore();
121
179
  const actionCause = ref<string>('');
122
180
  const loading = ref<boolean>(false);
181
+ const isPaperContract = ref<boolean>(false);
182
+ const isScansDocuments = ref<boolean>(false);
183
+ const isQr = ref<boolean>(false);
184
+ const isElectronicContract = ref<boolean>(true);
185
+ const email = ref<string>('');
186
+ const qrUrl = ref<string>('');
187
+ const connection = ref<any>(null);
188
+ const isQrLoading = ref<boolean>(false);
189
+ const urlCopy = ref<string>('');
190
+
123
191
  const vForm = ref<any>();
124
192
  const isSendNumberOpen = ref<boolean>(false);
125
193
  const phoneNumber = ref<string | null>(formStore.policyholderForm.phoneNumber ?? '');
@@ -137,6 +205,8 @@ export default defineComponent({
137
205
  fileTypeCode: documentDict.value ? documentDict.value.code : '',
138
206
  });
139
207
  const affiliationFormData = ref(new FormData());
208
+ const scansFormData = ref(new FormData());
209
+ const scansFiles = ref<any[]>([]);
140
210
 
141
211
  const openSmsPanel = (signInfo: SignUrlType) => {
142
212
  if (signInfo) {
@@ -166,6 +236,63 @@ export default defineComponent({
166
236
  }
167
237
  };
168
238
 
239
+ const onFileChangeScans = async (event: InputEvent, type: 'statement' | 'contract' | 'app' | 'attorney') => {
240
+ if (event.target) {
241
+ const files = (event.target as HTMLInputElement).files;
242
+ if (files && files.length) {
243
+ const doc = await selectedDocument(type);
244
+ const data = {
245
+ processInstanceId: formStore.applicationData.processInstanceId,
246
+ fileTypeCode: doc ? doc.code : null,
247
+ fileTypeId: doc ? doc.id : null,
248
+ fileName: files[0].name,
249
+ };
250
+ scansFiles.value.push({
251
+ file: files[0],
252
+ fileData: JSON.stringify([data]),
253
+ });
254
+ }
255
+ }
256
+ };
257
+
258
+ const onClearFile = async (type: 'statement' | 'contract' | 'app' | 'attorney') => {
259
+ const doc = await selectedDocument(type);
260
+ const result = scansFiles.value.filter(i => JSON.parse(i.fileData)[0].fileTypeCode !== doc.code);
261
+ scansFiles.value = result;
262
+ };
263
+
264
+ const selectedDocument = (type: 'statement' | 'contract' | 'app' | 'attorney') => {
265
+ let selectedDocument: any;
266
+ if (type === 'statement') {
267
+ selectedDocument = dataStore.dicFileTypeList.find((i: Value) => i.code === '32');
268
+ }
269
+ if (type === 'contract') {
270
+ selectedDocument = dataStore.dicFileTypeList.find((i: Value) => i.code === '6');
271
+ }
272
+ if (type === 'app') {
273
+ selectedDocument = dataStore.dicFileTypeList.find((i: Value) => i.code === '33');
274
+ }
275
+ if (type === 'attorney') {
276
+ selectedDocument = dataStore.dicFileTypeList.find((i: Value) => i.code === '34');
277
+ }
278
+ return selectedDocument;
279
+ };
280
+
281
+ const sendFiles = async () => {
282
+ if (scansFiles.value.length !== 4) {
283
+ dataStore.showToaster('warning', dataStore.t('toaster.notAllDocumentsAttached'));
284
+ return;
285
+ }
286
+ for (const item of scansFiles.value) {
287
+ scansFormData.value.append('file', item.file);
288
+ scansFormData.value.append('fileData', item.fileData);
289
+ await dataStore.uploadFiles(scansFormData.value);
290
+ scansFormData.value = new FormData();
291
+ }
292
+ closePanel();
293
+ dataStore.showToaster('success', dataStore.t('toaster.successOperation'));
294
+ await dataStore.handleTask(constants.actions.signed, route.params.taskId as string, actionCause.value);
295
+ };
169
296
  const submitForm = async () => {
170
297
  await vForm.value.validate().then(async (v: { valid: Boolean; errors: any }) => {
171
298
  if (v.valid) {
@@ -198,10 +325,32 @@ export default defineComponent({
198
325
 
199
326
  const handleTask = async () => {
200
327
  loading.value = true;
201
- await dataStore.handleTask(dataStore.panelAction, route.params.taskId as string, actionCause.value);
328
+ // Пока не нужно, на всякий оставить
329
+ // if (needRecalculation.value) {
330
+ // dataStore.showToaster('info', dataStore.t('toaster.needToRecalculate'));
331
+ // loading.value = false;
332
+ // return;
333
+ // }
334
+ if (dataStore.isAML || dataStore.isCheckContract || dataStore.isCheckContragent || dataStore.isDas) {
335
+ emit('task', [dataStore.panelAction, route.params.taskId as string, actionCause.value]);
336
+ } else {
337
+ await dataStore.handleTask(dataStore.panelAction, route.params.taskId as string, actionCause.value);
338
+ }
202
339
  loading.value = false;
203
340
  };
204
341
 
342
+ const onInit = async () => {
343
+ if (dataStore.controls.hasChooseSign) {
344
+ if (dataStore.isGons || dataStore.isLifeBusiness) {
345
+ isElectronicContract.value = false;
346
+ }
347
+ }
348
+ };
349
+
350
+ onMounted(async () => {
351
+ await onInit();
352
+ });
353
+
205
354
  const buttonText = computed(() => {
206
355
  switch (dataStore.panelAction) {
207
356
  case constants.actions.reject:
@@ -218,36 +367,187 @@ export default defineComponent({
218
367
  case constants.actions.register:
219
368
  return dataStore.t('buttons.register');
220
369
  case constants.actions.affiliate:
370
+ case constants.actions.template:
371
+ return dataStore.t('buttons.send');
372
+ default:
221
373
  return dataStore.t('buttons.send');
222
374
  }
223
375
  });
224
376
 
377
+ const panelTitle = computed(() => {
378
+ if (dataStore.isLifeBusiness && dataStore.panelAction === constants.actions.template) {
379
+ return dataStore.t('template');
380
+ }
381
+ return buttonText.value;
382
+ });
383
+
225
384
  watch(
226
385
  () => dataStore.panelAction,
227
386
  val => {
228
387
  if (!!val) {
229
- dataStore.panel.title = buttonText.value!;
388
+ dataStore.panel.title = panelTitle.value;
230
389
  dataStore.panel.open = true;
231
390
  }
232
391
  },
233
392
  { immediate: true },
234
393
  );
394
+
395
+ const needRecalculation = computed(
396
+ () =>
397
+ dataStore.isGons &&
398
+ formStore.applicationData.statusCode === 'UnderwriterForm' &&
399
+ dataStore.panelAction === constants.actions.accept &&
400
+ formStore.productConditionsForm.isRecalculated === false,
401
+ );
235
402
  const sendingActions = computed(
236
403
  () => dataStore.panelAction === constants.actions.reject || dataStore.panelAction === constants.actions.return || dataStore.panelAction === constants.actions.rejectclient,
237
404
  );
238
405
  const acceptAction = computed(() => dataStore.panelAction === constants.actions.accept);
406
+ const templateAction = computed(() => dataStore.panelAction === constants.actions.template);
239
407
  const signingActions = computed(() => dataStore.panelAction === constants.actions.sign);
240
408
  const payingActions = computed(() => dataStore.panelAction === constants.actions.pay);
241
409
  const affiliateActions = computed(() => dataStore.panelAction === constants.actions.affiliate);
410
+ const chooseSignActions = computed(() => dataStore.controls.hasChooseSign && dataStore.panelAction === constants.actions.chooseSign);
411
+
242
412
  const paymentPeriod = computed(() => formStore.productConditionsForm.paymentPeriod.nameRu);
243
413
  const insurancePremiumPerMonth = computed(() => dataStore.getNumberWithSpaces(formStore.productConditionsForm.insurancePremiumPerMonth));
244
- const requestedSumInsured = computed(() => dataStore.getNumberWithSpaces(formStore.productConditionsForm.requestedSumInsured));
414
+ const requestedSumInsured = computed(() => {
415
+ if (dataStore.isLifeBusiness && formStore.productConditionsForm.requestedSumInsured === null) {
416
+ return dataStore.getNumberWithSpaces(formStore.applicationData.policyAppDto!.mainInsSum);
417
+ }
418
+ return dataStore.getNumberWithSpaces(formStore.productConditionsForm.requestedSumInsured);
419
+ });
420
+ const price = computed(() => dataStore.getNumberWithSpaces(formStore.productConditionsForm.calculatorForm.price));
421
+ const insuredAmount = computed(() => formStore.productConditionsForm.calculatorForm.amount!.nameRu! + dataStore.currency);
245
422
  const hasConditionsInfo = computed(() => {
423
+ if (dataStore.isLifetrip || dataStore.isDas) {
424
+ return false;
425
+ }
246
426
  if (dataStore.isFinCenter()) {
247
427
  return false;
248
428
  }
249
429
  return true;
250
430
  });
431
+ const isPaperDisabled = computed(() => {
432
+ if (dataStore.isGons) {
433
+ return false;
434
+ }
435
+ return true;
436
+ });
437
+ const isElectronicDisabled = computed(() => {
438
+ if (dataStore.isGons) {
439
+ return true;
440
+ }
441
+ return false;
442
+ });
443
+ const isScansDisabled = computed(() => {
444
+ if (dataStore.isGons) {
445
+ return true;
446
+ }
447
+ return false;
448
+ });
449
+ const isQrDisabled = computed(() => {
450
+ if (dataStore.isLifeBusiness) {
451
+ return false;
452
+ }
453
+ return true;
454
+ });
455
+ const downloadTemplate = async (documentType: number, fileType: string) => {
456
+ await dataStore.downloadTemplate(documentType, fileType);
457
+ };
458
+
459
+ const sendTemplateToEmail = async () => {
460
+ await vForm.value.validate().then(async (v: { valid: Boolean; errors: any }) => {
461
+ if (v.valid) {
462
+ dataStore.panel.open = false;
463
+ dataStore.panelAction = null;
464
+ await dataStore.sendTemplateToEmail(email.value);
465
+ }
466
+ });
467
+ };
468
+
469
+ const handleSignAction = async (type: 'paper' | 'electronic' | 'scans' | 'qr') => {
470
+ loading.value = true;
471
+ if (type === 'electronic') {
472
+ await dataStore.signDocument();
473
+ isElectronicContract.value = true;
474
+ }
475
+ if (type === 'paper') {
476
+ isPaperContract.value = true;
477
+ }
478
+ if (type === 'scans') {
479
+ isScansDocuments.value = true;
480
+ }
481
+ if (type === 'qr') {
482
+ const result = (await dataStore.signDocument('qr')) as any;
483
+ if (result && result.data) {
484
+ const groupId = result.data[0].signatureDocumentGroupId;
485
+ await generateQR(groupId);
486
+ isQr.value = true;
487
+ }
488
+ }
489
+ loading.value = false;
490
+ };
491
+
492
+ // TODO Рефактор QR c npm
493
+ const generateQR = async (groupId: string) => {
494
+ const uuid = crypto.randomUUID();
495
+ const qrValue = `${getValuePerEnv('qrGenUrl')}/${uuid}/${groupId}`;
496
+ qrUrl.value = `https://api.qrserver.com/v1/create-qr-code/?size=135x135&data=${qrValue}`;
497
+
498
+ if (dataStore.isLifeBusiness) {
499
+ //для юр лиц
500
+ urlCopy.value = `https://egovbusiness.page.link/?link=${qrValue}?mgovSign&amp;apn=kz.mobile.mgov.business&amp;isi=1597880144&amp;ibi=kz.mobile.mgov.business`;
501
+ } else {
502
+ //для физ лиц
503
+ urlCopy.value = `https://mgovsign.page.link/?link=${qrValue}?mgovSign&amp;apn=kz.mobile.mgov&amp;isi=1476128386&amp;ibi=kz.egov.mobile`;
504
+ }
505
+
506
+ await startConnection(uuid);
507
+ };
508
+
509
+ const startConnection = async (uuid: string) => {
510
+ connection.value = new HubConnectionBuilder().withUrl(`https://test-sign.halyklife.kz/qrhub/${uuid}`).withAutomaticReconnect().build();
511
+ try {
512
+ await connection.value.start();
513
+ console.log('SignalR connection started.');
514
+ connection.value.on('QR', async (message: any) => {
515
+ if (message === 'Opened') {
516
+ isQrLoading.value = true;
517
+ }
518
+ if (message === 'Signed') {
519
+ isQrLoading.value = false;
520
+ dataStore.showToaster('success', dataStore.t('sign.successQrSigned'));
521
+ qrUrl.value = '';
522
+ isQr.value = false;
523
+ dataStore.panel.open = false;
524
+ dataStore.panelAction = null;
525
+ await stopConnection();
526
+ }
527
+ });
528
+ } catch (err) {
529
+ console.error('Error starting SignalR connection:', err);
530
+ }
531
+ };
532
+
533
+ const closeQrPanel = async () => {
534
+ isQr.value = false;
535
+ isQrLoading.value = false;
536
+ await stopConnection();
537
+ };
538
+
539
+ const stopConnection = async () => {
540
+ if (connection.value) {
541
+ await connection.value.stop();
542
+ console.log('SignalR connection stopped.');
543
+ }
544
+ };
545
+
546
+ const generateDocument = async () => {
547
+ dataStore.panel.open = false;
548
+ dataStore.panelAction = null;
549
+ await dataStore.generateDocument();
550
+ };
251
551
 
252
552
  return {
253
553
  // State
@@ -258,6 +558,14 @@ export default defineComponent({
258
558
  isSendNumberOpen,
259
559
  phoneNumber,
260
560
  selectedClient,
561
+ isPaperContract,
562
+ isScansDocuments,
563
+ email,
564
+ isQr,
565
+ qrUrl,
566
+ scansFiles,
567
+ isQrLoading,
568
+ urlCopy,
261
569
 
262
570
  // Functions
263
571
  closePanel,
@@ -266,6 +574,12 @@ export default defineComponent({
266
574
  openSmsPanel,
267
575
  openEpayPanel,
268
576
  onFileChange,
577
+ downloadTemplate,
578
+ sendTemplateToEmail,
579
+ onFileChangeScans,
580
+ sendFiles,
581
+ onClearFile,
582
+ closeQrPanel,
269
583
 
270
584
  // Computed
271
585
  buttonText,
@@ -274,11 +588,22 @@ export default defineComponent({
274
588
  payingActions,
275
589
  acceptAction,
276
590
  affiliateActions,
591
+ chooseSignActions,
277
592
  paymentPeriod,
278
593
  insurancePremiumPerMonth,
279
594
  requestedSumInsured,
280
595
  affiliationDocument,
281
596
  hasConditionsInfo,
597
+ price,
598
+ insuredAmount,
599
+ templateAction,
600
+ isElectronicContract,
601
+ handleSignAction,
602
+ generateDocument,
603
+ isPaperDisabled,
604
+ isElectronicDisabled,
605
+ isScansDisabled,
606
+ isQrDisabled,
282
607
  };
283
608
  },
284
609
  });
@@ -288,16 +613,19 @@ export default defineComponent({
288
613
  .v-expansion-panel-title__overlay {
289
614
  background: #ffffff;
290
615
  }
616
+
291
617
  .v-expansion-panel-title {
292
618
  height: 70px !important;
293
619
  padding: 10px 20px !important;
294
620
  }
621
+
295
622
  .v-expansion-panels--variant-accordion > :last-child {
296
623
  border-top-left-radius: 0.5rem !important;
297
624
  border-top-right-radius: 0.5rem !important;
298
625
  border-top-left-radius: 0.5rem !important;
299
626
  border-radius: 0.5rem !important;
300
627
  }
628
+
301
629
  .v-expansion-panel-text__wrapper {
302
630
  padding: 10px 20px !important;
303
631
  }
@@ -1,7 +1,10 @@
1
1
  <template>
2
- <div class="flex justify-between p-4 items-center cursor-pointer" :class="[$styles.rounded, $styles.blueBgLight, $styles.blueBgLightHover]">
2
+ <div
3
+ class="transition-all flex justify-between p-4 items-center cursor-pointer"
4
+ :class="[$styles.rounded, $styles.blueBgLight, $styles.blueBgLightHover, disabled ? $styles.disabled : '']"
5
+ >
3
6
  <span :class="[$styles.textSimple]">{{ text }}</span>
4
- <i class="mdi text-xl" :class="[selected ? `mdi-radiobox-marked ${$styles.greenText}` : 'mdi-radiobox-blank text-[#636363]']"></i>
7
+ <i class="mdi text-xl" :class="[selected ? `${trueIcon} ${$styles.greenText}` : `${falseIcon} text-[#636363]`]"></i>
5
8
  </div>
6
9
  </template>
7
10
 
@@ -15,6 +18,18 @@ export default defineComponent({
15
18
  type: Boolean,
16
19
  default: false,
17
20
  },
21
+ disabled: {
22
+ type: Boolean,
23
+ default: false,
24
+ },
25
+ trueIcon: {
26
+ type: String,
27
+ default: 'mdi-radiobox-marked',
28
+ },
29
+ falseIcon: {
30
+ type: String,
31
+ default: 'mdi-radiobox-blank ',
32
+ },
18
33
  },
19
34
  });
20
35
  </script>
@@ -0,0 +1,7 @@
1
+ <script setup lang="ts">
2
+ const dataStore = useDataStore();
3
+
4
+ onUnmounted(() => {
5
+ dataStore.rightPanel.open = false;
6
+ });
7
+ </script>
@@ -0,0 +1,28 @@
1
+ <template>
2
+ <component v-if="!!type && Object.keys(vuetifyAnimations).includes(type)" :is="vuetifyAnimations[type]">
3
+ <slot></slot>
4
+ </component>
5
+ <slot v-else></slot>
6
+ </template>
7
+
8
+ <script setup lang="ts">
9
+ defineProps({
10
+ type: {
11
+ type: String as PropType<VuetifyAnimations>,
12
+ required: false,
13
+ },
14
+ });
15
+
16
+ const vuetifyAnimations: { [key in VuetifyAnimations]: string } = {
17
+ expand: 'v-expand-transition',
18
+ fab: 'v-fab-transition',
19
+ fade: 'v-fade-transition',
20
+ scale: 'v-scale-transition',
21
+ 'scroll-x': 'v-scroll-x-transition',
22
+ 'scroll-y': 'v-scroll-x-transition',
23
+ 'slide-x': 'v-slide-x-transition',
24
+ 'slide-x-r': 'v-slide-x-reverse-transition',
25
+ 'slide-y': 'v-slide-y-transition',
26
+ 'slide-y-r': 'v-slide-y-reverse-transition',
27
+ };
28
+ </script>
@@ -1,9 +1,10 @@
1
1
  import axios from 'axios';
2
2
  import interceptors from '../api/interceptors';
3
3
 
4
- export const useAxios = (baseURL: string) => {
4
+ export const useAxiosInstance = (baseURL: string) => {
5
5
  const axiosInstance = axios.create({
6
6
  baseURL: baseURL,
7
+ signal: useDataStore().rController.signal,
7
8
  });
8
9
  interceptors(axiosInstance);
9
10