hl-core 0.0.10-beta.7 → 0.0.10-beta.70

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 (49) hide show
  1. package/README.md +0 -2
  2. package/api/base.api.ts +425 -134
  3. package/api/interceptors.ts +162 -62
  4. package/components/Dialog/Dialog.vue +5 -1
  5. package/components/Dialog/DigitalDocumentsDialog.vue +129 -0
  6. package/components/Dialog/FamilyDialog.vue +15 -4
  7. package/components/Form/DigitalDocument.vue +52 -0
  8. package/components/Form/FormSource.vue +30 -0
  9. package/components/Form/ManagerAttachment.vue +85 -11
  10. package/components/Form/ProductConditionsBlock.vue +12 -6
  11. package/components/Input/Datepicker.vue +5 -0
  12. package/components/Input/FileInput.vue +1 -1
  13. package/components/Input/FormInput.vue +7 -0
  14. package/components/Input/OtpInput.vue +25 -0
  15. package/components/Input/RoundedInput.vue +2 -0
  16. package/components/Input/RoundedSelect.vue +2 -0
  17. package/components/Input/TextAreaField.vue +71 -0
  18. package/components/Input/TextHint.vue +13 -0
  19. package/components/Layout/SettingsPanel.vue +2 -1
  20. package/components/Menu/MenuNav.vue +2 -1
  21. package/components/Pages/Anketa.vue +207 -176
  22. package/components/Pages/Auth.vue +10 -3
  23. package/components/Pages/ContragentForm.vue +24 -18
  24. package/components/Pages/Documents.vue +488 -66
  25. package/components/Pages/MemberForm.vue +1009 -268
  26. package/components/Pages/ProductConditions.vue +1424 -273
  27. package/components/Panel/PanelHandler.vue +329 -126
  28. package/components/Utilities/Chip.vue +1 -1
  29. package/components/Utilities/JsonViewer.vue +1 -2
  30. package/composables/classes.ts +136 -20
  31. package/composables/constants.ts +168 -1
  32. package/composables/index.ts +467 -9
  33. package/composables/styles.ts +8 -24
  34. package/configs/i18n.ts +2 -0
  35. package/configs/pwa.ts +1 -7
  36. package/layouts/clear.vue +1 -1
  37. package/layouts/default.vue +2 -2
  38. package/layouts/full.vue +1 -1
  39. package/locales/kz.json +1239 -0
  40. package/locales/ru.json +133 -21
  41. package/nuxt.config.ts +8 -6
  42. package/package.json +14 -13
  43. package/plugins/head.ts +7 -1
  44. package/plugins/helperFunctionsPlugins.ts +1 -0
  45. package/store/data.store.ts +1080 -552
  46. package/store/member.store.ts +19 -8
  47. package/store/rules.ts +75 -8
  48. package/types/enum.ts +52 -2
  49. package/types/index.ts +143 -6
@@ -1,10 +1,11 @@
1
1
  import { useDisplay } from 'vuetify';
2
- import jwt_decode from 'jwt-decode';
2
+ import { jwtDecode as jwt_decode } from 'jwt-decode';
3
3
  import { XMLParser } from 'fast-xml-parser';
4
4
  import { AxiosError } from 'axios';
5
5
  import { DocumentReaderApi, Scenario, TextFieldType, LCID } from '@regulaforensics/document-reader-webclient';
6
- import { PolicyholderClass } from '../composables/classes';
7
- import type { EnvModes, NestedKeyOf, ResponseStructure } from '../types';
6
+ import { PolicyholderClass, Value, User } from '../composables/classes';
7
+ import type { EnvModes, NestedKeyOf, Projects, ResponseStructure, Utils, RouteType } from '../types';
8
+ import { Roles, Statuses } from '../types/enum';
8
9
 
9
10
  export const useEnv = () => {
10
11
  return {
@@ -17,10 +18,12 @@ export const useEnv = () => {
17
18
 
18
19
  export class Masks {
19
20
  numbers: string = '#*';
20
- otp: string = '# # # #';
21
+ otp: string = '####';
22
+ otpSixDigit: string = '######';
21
23
  spacedNumbers: string = '### ### ### ### ### ### ###';
22
24
  iin: string = '###-###-###-###';
23
25
  phone: string = '+7 (7##) ### ## ##';
26
+ phoneNonResident: string = '+###############';
24
27
  date: string = '##.##.####';
25
28
  post: string = '######';
26
29
  threeDigit: string = '###';
@@ -45,6 +48,16 @@ export const getNumber = (number: string) => {
45
48
  return number ? Number(number.replace(/\s/g, '')) : null;
46
49
  };
47
50
 
51
+ export const parseAmount = (value: number | string | null): number | null => {
52
+ if (value === null) return null;
53
+ if (typeof value === 'number') return value;
54
+
55
+ const normalized = value.replace(/\s+/g, '');
56
+ const num = Number(normalized);
57
+
58
+ return Number.isNaN(num) ? null : num;
59
+ };
60
+
48
61
  export const formatDate = (date: string) => {
49
62
  if (date) {
50
63
  const data = date.split('.');
@@ -87,6 +100,29 @@ export const reformatDate = (date: string) => {
87
100
  }
88
101
  };
89
102
 
103
+ export const reformatDateWithHours = (date: string) => {
104
+ if (date) {
105
+ const data = new Date(date);
106
+ let day: string | number = data.getDate();
107
+ let month: string | number = data.getMonth() + 1;
108
+ let hour: string | number = data.getHours();
109
+ let minute: string | number = data.getMinutes();
110
+ if (month < 10) {
111
+ month = '0' + month;
112
+ }
113
+ if (day < 10) {
114
+ day = '0' + day;
115
+ }
116
+ if (minute < 10) {
117
+ minute = '0' + minute;
118
+ }
119
+ const year = data.getFullYear();
120
+ return `${day}.${month}.${year} - ${hour}:${minute}`;
121
+ } else {
122
+ return null;
123
+ }
124
+ };
125
+
90
126
  export const reformatIin = (iin: string) => {
91
127
  if (!!iin) {
92
128
  const matched = iin.match(/.{1,3}/g);
@@ -102,13 +138,22 @@ export const formatPhone = (phone: string) => {
102
138
 
103
139
  export const cleanWhiteSpace = (str: string) => String(str).replace(/\s+/g, '');
104
140
 
105
- export const jwtDecode = (token: string): any => {
106
- if (token) return jwt_decode(token);
141
+ export const jwtDecode = (token?: string | null) => {
142
+ if (token) return jwt_decode<Utils.JwtToken>(token);
107
143
  else return null;
108
144
  };
109
145
 
110
146
  export const isValidToken = (token: string) => {
111
- return (new Date(jwtDecode(token).exp * 1000).getTime() - Date.now()) / 1000 > 0;
147
+ try {
148
+ if (token) {
149
+ const decoded = jwtDecode(token);
150
+ return !!decoded && (new Date(Number(decoded.exp) * 1000).getTime() - Date.now()) / 1000 > 0;
151
+ }
152
+ return false;
153
+ } catch (err) {
154
+ console.log(err);
155
+ return false;
156
+ }
112
157
  };
113
158
 
114
159
  export const isValidGUID = (value: string) => {
@@ -147,8 +192,16 @@ export const parseProcents = (val: string | number) => (val ? Number(((val as nu
147
192
 
148
193
  export const formatProcents = (val: string | number) => (val ? Number(((val as number) / 100).toFixed(2)) : Number(val));
149
194
 
195
+ export const formatSpacedNumber = (val: any) => ((!isNaN(val) && val !== null) || typeof val === 'string' ? Number(String(val).replace(/\s/g, '')) : 0);
196
+
150
197
  export const sanitizeURL = (text: string) => (text ? text.replace(/\r?\n|\r|\\|"/g, '') : '');
151
198
 
199
+ export const sanitize = (text: string) =>
200
+ String(text)
201
+ .replace(/\r?\n|\r/g, '')
202
+ .replace(/\\/g, '')
203
+ .replace(/"/g, '');
204
+
152
205
  export const yearEnding = (number: number, titles: string[], cases: number[]) => {
153
206
  return titles[number % 100 > 4 && number % 100 < 20 ? 2 : cases[number % 10 < 5 ? number % 10 : 5]];
154
207
  };
@@ -222,7 +275,7 @@ export const policyholderToBeneficialOwner = (isPolicyholderBeneficialOwner: boo
222
275
  beneficialOwner.citizenship = policyholder.clientData.authoritedPerson.citizenship;
223
276
  beneficialOwner.birthDate = policyholder.clientData.authoritedPerson.birthDate;
224
277
  beneficialOwner.gender = policyholder.clientData.authoritedPerson.gender;
225
- beneficialOwner.resident = policyholder.clientData.resident;
278
+ beneficialOwner.resident = policyholder.clientData.authoritedPerson.resident;
226
279
  beneficialOwner.taxResidentCountry = policyholder.clientData.taxResidentCountry;
227
280
  beneficialOwner.economySectorCode = policyholder.clientData.economySectorCode;
228
281
  beneficialOwner.identityDocument.issuedOn = policyholder.clientData.authoritedPerson.identityDocument.issuedOn;
@@ -274,6 +327,7 @@ export const setAddressBeneficiary = (whichIndex: number, sameAddress: boolean)
274
327
  if (beneficiary.id === 0) {
275
328
  beneficiary.registrationCity = new Value();
276
329
  beneficiary.registrationCountry = new Value();
330
+ beneficiary.birthPlace = new Value();
277
331
  beneficiary.registrationMicroDistrict = '';
278
332
  beneficiary.registrationNumberApartment = '';
279
333
  beneficiary.registrationNumberApartment = '';
@@ -296,6 +350,13 @@ export const setAddressBeneficiary = (whichIndex: number, sameAddress: boolean)
296
350
  const city = dataStore.cities.find(i => i.nameRu === cityName.replace('г.', ''));
297
351
  beneficiary.registrationCity = city ?? new Value();
298
352
  }
353
+ const contragentData = beneficiary.response.contragent;
354
+ if (contragentData) {
355
+ const country = dataStore.countries.find((i: Value) => i.nameRu?.match(new RegExp(contragentData.birthPlace, 'i')));
356
+ beneficiary.birthPlace = country ?? new Value();
357
+ } else {
358
+ beneficiary.birthPlace = new Value();
359
+ }
299
360
  const province = dataStore.states.find(i => i.ids === benAddress[0].stateCode);
300
361
  const localityType = dataStore.localityTypes.find(i => i.nameRu === benAddress[0].cityTypeName);
301
362
  const region = dataStore.regions.find(i => i.ids == benAddress[0].regionCode);
@@ -333,6 +394,7 @@ export const setAddressInsured = (whichIndex: number, sameAddress: boolean) => {
333
394
  if (insured.id === 0) {
334
395
  insured.registrationCity = new Value();
335
396
  insured.registrationCountry = new Value();
397
+ insured.birthPlace = new Value();
336
398
  insured.registrationMicroDistrict = '';
337
399
  insured.registrationNumberApartment = '';
338
400
  insured.registrationNumberApartment = '';
@@ -355,6 +417,13 @@ export const setAddressInsured = (whichIndex: number, sameAddress: boolean) => {
355
417
  const city = dataStore.cities.find(i => i.nameRu === cityName.replace('г.', ''));
356
418
  insured.registrationCity = city ?? new Value();
357
419
  }
420
+ const contragentData = insured.response.contragent;
421
+ if (contragentData) {
422
+ const country = dataStore.countries.find((i: Value) => i.nameRu?.match(new RegExp(contragentData.birthPlace, 'i')));
423
+ insured.birthPlace = country ?? new Value();
424
+ } else {
425
+ insured.birthPlace = new Value();
426
+ }
358
427
  const province = dataStore.states.find(i => i.ids === benAddress[0].stateCode);
359
428
  const localityType = dataStore.localityTypes.find(i => i.nameRu === benAddress[0].cityTypeName);
360
429
  const region = dataStore.regions.find(i => i.ids == benAddress[0].regionCode);
@@ -410,7 +479,8 @@ type WhichValuePerEnv =
410
479
  | 'efoBaseApi'
411
480
  | 'efoBaseApiLocal'
412
481
  | 'amlBaseApi'
413
- | 'amlBaseApiLocal';
482
+ | 'amlBaseApiLocal'
483
+ | 'lkaUrl';
414
484
 
415
485
  export const getStrValuePerEnv = (which: WhichValuePerEnv) => {
416
486
  const valuesPerEnv: {
@@ -473,6 +543,11 @@ export const getStrValuePerEnv = (which: WhichValuePerEnv) => {
473
543
  development: 'http://aml-dev.halyklife.nb/api',
474
544
  test: 'http://aml-dev.halyklife.nb/api',
475
545
  },
546
+ lkaUrl: {
547
+ production: '/#/efo',
548
+ development: '/#/efo',
549
+ test: '/#/efo',
550
+ },
476
551
  };
477
552
  return valuesPerEnv[which][import.meta.env.VITE_MODE as EnvModes];
478
553
  };
@@ -491,6 +566,83 @@ export const getMainPageRoute = () => {
491
566
  return 'index';
492
567
  };
493
568
 
569
+ export const validateToken = (to: RouteType) => {
570
+ const dataStore = useDataStore();
571
+ if (to.query) {
572
+ if ('token' in to.query) {
573
+ const token = to.query.token as string;
574
+ if (isValidToken(token)) {
575
+ localStorage.setItem('accessToken', token);
576
+ dataStore.accessToken = token;
577
+ dataStore.getUserRoles();
578
+ }
579
+ } else {
580
+ const token = localStorage.getItem('accessToken') || null;
581
+ if (token && isValidToken(token)) {
582
+ dataStore.accessToken = token;
583
+ dataStore.getUserRoles();
584
+ } else {
585
+ dataStore.sendToParent(constants.postActions.toHomePage, dataStore.t('toaster.tokenExpire'));
586
+ }
587
+ }
588
+ }
589
+ };
590
+
591
+ export const validateRoute = (to: RouteType) => {
592
+ const dataStore = useDataStore();
593
+ const token = localStorage.getItem('accessToken') || null;
594
+ if (to && to.meta && 'requiresAuth' in to.meta && to.meta.requiresAuth && (!token || (token && isValidToken(token) === false))) {
595
+ localStorage.clear();
596
+ dataStore.sendToParent(constants.postActions.toHomePage, dataStore.t('toaster.tokenExpire'));
597
+ }
598
+ };
599
+
600
+ export const validateSettingsPanel = () => {
601
+ const dataStore = useDataStore();
602
+ const formStore = useFormStore();
603
+ const hasPanelItem = (id: string) => {
604
+ return !!Object.values(dataStore.settings.items).find(i => i.id === id);
605
+ };
606
+ // Bug in getApplicationData, if there is empty member it didn't update
607
+ // if (!hasPanelItem('reload') && route.params.taskId !== '0') {
608
+ // dataStore.settings.items.push(
609
+ // new MenuItem({
610
+ // id: 'reload',
611
+ // title: dataStore.t('buttons.reload'),
612
+ // icon: 'mdi-reload',
613
+ // action: async () => await dataStore.getApplicationData(route.params.taskId),
614
+ // }),
615
+ // );
616
+ // }
617
+ if (!hasPanelItem('reject') && dataStore.isInitiator()) {
618
+ dataStore.settings.items.push(
619
+ new MenuItem({
620
+ id: 'reject',
621
+ title: dataStore.t('buttons.cancelApplication'),
622
+ icon: 'mdi-close',
623
+ action: () => (dataStore.panelAction = constants.actions.rejectclient),
624
+ show: computed(() => dataStore.isTask() && dataStore.isProcessCancel(formStore.applicationData.statusCode)),
625
+ }),
626
+ );
627
+ }
628
+ if (!hasPanelItem('return') && (dataStore.isInitiator() || dataStore.isUnderwriter())) {
629
+ dataStore.settings.items.push(
630
+ new MenuItem({
631
+ id: 'return',
632
+ title: dataStore.t('buttons.returnStatement'),
633
+ icon: 'mdi-restore',
634
+ action: () => (dataStore.panelAction = constants.actions.return),
635
+ show: computed(() => dataStore.isTask() && dataStore.isProcessReturnable(formStore.applicationData.statusCode)),
636
+ }),
637
+ );
638
+ }
639
+ };
640
+
641
+ export const isIframe = () => {
642
+ if (window.location.hostname !== 'localhost' && useEnv().isProduction) return window.self !== window.top;
643
+ return true;
644
+ };
645
+
494
646
  export const keyDeleter = <T extends object>(data: T, keys: Array<NestedKeyOf<T>>) => {
495
647
  if (typeof data === 'object' && !!data && keys && Array.isArray(keys) && keys.length) {
496
648
  keys.forEach(key => {
@@ -610,3 +762,309 @@ export const isEveryFormDisabled = (isDisabledForm: any) => {
610
762
  };
611
763
 
612
764
  export class ApiError extends AxiosError<any, any> {}
765
+
766
+ export class ProcessController {
767
+ isProcessEditable = (statusCode?: keyof typeof Statuses) => {
768
+ const getEditibleStatuses = () => {
769
+ const defaultStatuses = constants.editableStatuses;
770
+ return defaultStatuses;
771
+ };
772
+ return !!getEditibleStatuses().find(status => status === statusCode);
773
+ };
774
+ isProcessReturnable = (statusCode?: keyof typeof Statuses) => {
775
+ const getReturnableStatuses = () => {
776
+ const defaultStatuses = constants.returnStatementStatuses;
777
+ return defaultStatuses;
778
+ };
779
+ return !!getReturnableStatuses().find(status => status === statusCode);
780
+ };
781
+ isProcessCancel = (statusCode?: keyof typeof Statuses) => {
782
+ const getCanceleStatuses = () => {
783
+ const defaultStatuses = constants.cancelApplicationStatuses;
784
+ return defaultStatuses;
785
+ };
786
+ return !!getCanceleStatuses().find(status => status === statusCode);
787
+ };
788
+ isProcessReject = (statusCode?: keyof typeof Statuses) => {
789
+ const getRejectStatuses = () => {
790
+ const defaultStatuses = constants.rejectApplicationStatuses;
791
+ return defaultStatuses;
792
+ };
793
+ return !!getRejectStatuses().find(status => status === statusCode);
794
+ };
795
+ }
796
+
797
+ export class RoleController {
798
+ user: User = new User();
799
+
800
+ isRole = (whichRole: keyof typeof Roles) => {
801
+ if (this.user.roles.length === 0) {
802
+ const token = localStorage.getItem('accessToken') || null;
803
+ if (token) {
804
+ const decoded = jwtDecode(token);
805
+ if (decoded) {
806
+ this.user.id = String(decoded.sub);
807
+ this.user.fullName = `${decoded.lastName} ${decoded.firstName} ${decoded.middleName ?? ''}`;
808
+ this.user.code = decoded.code;
809
+ this.user.branchCode = decoded.branchCode;
810
+ const key = getKeyWithPattern(decoded, 'role');
811
+ if (key) {
812
+ const roles = decoded[key as keyof Utils.JwtToken];
813
+ if (typeof roles === 'string') {
814
+ this.user.roles.push(roles);
815
+ } else if (typeof roles === 'object') {
816
+ this.user.roles = roles;
817
+ }
818
+ }
819
+ }
820
+ }
821
+ }
822
+ return !!this.user.roles.find(i => i === whichRole);
823
+ };
824
+ isInitiator = (productFromExternal?: string) => {
825
+ const env = useEnv();
826
+ const dataStore = useDataStore();
827
+ const hasAccessByProduct = (() => {
828
+ const product = productFromExternal as Projects;
829
+ if (dataStore.isLifetrip || product === 'lifetrip') return this.isBranchDirector() || this.isTravelAgent();
830
+ if (dataStore.isPension || product === 'pensionannuitynew') return this.isBranchDirector() || this.isExecutor() || this.isRegionDirector();
831
+ if (dataStore.isLifeBusiness || product === 'lifebusiness') return this.isHeadManager() || this.isBranchDirector() || this.isRegionDirector();
832
+ if (dataStore.isCritical || product === 'criticalillness') return this.isBranchDirector();
833
+ return false;
834
+ })();
835
+ return (
836
+ this.isManager() ||
837
+ this.isSalesManager() ||
838
+ this.isChiefSalesManager() ||
839
+ this.isChiefManagerNSZH() ||
840
+ this.isAgent() ||
841
+ this.isAgentMycar() ||
842
+ this.isManagerHalykBank() ||
843
+ this.isServiceManager() ||
844
+ this.isAgentAuletti() ||
845
+ hasAccessByProduct
846
+ );
847
+ };
848
+ isManager = () => this.isRole(constants.roles.Manager);
849
+ isSalesManager = () => this.isRole(constants.roles.SalesManager);
850
+ isChiefSalesManager = () => this.isRole(constants.roles.ChiefSalesManager);
851
+ isChiefManagerNSZH = () => this.isRole(constants.roles.ChiefManagerNSZH);
852
+ isCompliance = () => this.isRole(constants.roles.Compliance);
853
+ isAdmin = () => this.isRole(constants.roles.Admin);
854
+ isJurist = () => this.isRole(constants.roles.Jurist);
855
+ isAgent = () => this.isRole(constants.roles.Agent);
856
+ isManagerHalykBank = () => this.isRole(constants.roles.ManagerHalykBank);
857
+ isServiceManager = () => this.isRole(constants.roles.ServiceManager);
858
+ isUSNSsanctioner = () => this.isRole(constants.roles.USNSsanctioner);
859
+ isUnderwriter = () => this.isRole(constants.roles.Underwriter);
860
+ isActuary = () => this.isRole(constants.roles.Actuary);
861
+ isAgentMycar = () => this.isRole(constants.roles.AgentMycar);
862
+ isAgentAuletti = () => this.isRole(constants.roles.AgentAuletti);
863
+ isManagerAuletti = () => this.isRole(constants.roles.ManagerAuletti);
864
+ isAnalyst = () => this.isRole(constants.roles.Analyst);
865
+ isAuditor = () => this.isRole(constants.roles.Auditor);
866
+ isUpk = () => this.isRole(constants.roles.UPK);
867
+ isUrp = () => this.isRole(constants.roles.URP);
868
+ isUsns = () => this.isRole(constants.roles.USNS);
869
+ isNotAccumulativeSanctionerUSNS = () => this.isRole(constants.roles.NotAccumulativeSanctionerUSNS);
870
+ isAccountant = () => this.isRole(constants.roles.Accountant);
871
+ isDrn = () => this.isRole(constants.roles.DRNSJ);
872
+ isSupport = () => this.isRole(constants.roles.Support);
873
+ isFinCenter = () => this.isRole(constants.roles.FinCenter);
874
+ isSupervisor = () => this.isRole(constants.roles.Supervisor);
875
+ isHeadManager = () => this.isRole(constants.roles.HeadManager);
876
+ isBranchDirector = () => this.isRole(constants.roles.BranchDirector);
877
+ isRegionDirector = () => this.isRole(constants.roles.RegionDirector);
878
+ isUSNSACCINS = () => this.isRole(constants.roles.USNSACCINS);
879
+ isDsuio = () => this.isRole(constants.roles.Dsuio);
880
+ isHeadDso = () => this.isRole(constants.roles.HEADDSO);
881
+ isAdjuster = () => this.isRole(constants.roles.SettlementLosses);
882
+ isHeadAdjuster = () => this.isRole(constants.roles.HeadSettlementLosses);
883
+ isDsoDirector = () => this.isRole(constants.roles.DsoDirector);
884
+ isArchivist = () => this.isRole(constants.roles.Archivist);
885
+ isAccountantDirector = () => this.isRole(constants.roles.AccountantDirector);
886
+ isHeadOfDso = () => this.isRole(constants.roles.HeadOfDso);
887
+ isUrsp = () => this.isRole(constants.roles.URSP);
888
+ isExecutor = () => this.isRole(constants.roles.ExecutorGPH);
889
+ isDsuioOrv = () => this.isRole(constants.roles.DsuioOrv);
890
+ isUKP = () => this.isRole(constants.roles.UKP);
891
+ isDpDirector = () => this.isRole(constants.roles.DpDirector);
892
+ isSecurity = () => this.isRole(constants.roles.Security);
893
+ isURAP = () => this.isRole(constants.roles.URAP);
894
+ isTravelAgent = () => this.isRole(constants.roles.TravelAgent);
895
+ isHR = () => this.isRole(constants.roles.HR);
896
+ isReInsurer = () => this.isRole(constants.roles.ReInsurer);
897
+ isSanctioner1 = () => this.isRole(constants.roles.Sanctioner1);
898
+ isSanctioner2 = () => this.isRole(constants.roles.Sanctioner2);
899
+ isSanctioner3 = () => this.isRole(constants.roles.Sanctioner3);
900
+ hasAccess = () => {
901
+ const baseAccessRoles = this.isAdmin() || this.isSupport() || this.isAnalyst() || this.isDrn() || this.isDsuioOrv() || this.isAuditor();
902
+ return {
903
+ invoiceInfo: this.isAdmin() || this.isSupport(),
904
+ toLKA: this.isAgent() || this.isManagerHalykBank() || baseAccessRoles,
905
+ toLKAv2: this.isHR() || baseAccessRoles,
906
+ toAML: this.isCompliance() || baseAccessRoles,
907
+ toAULETTI: this.isAgentAuletti() || this.isManagerAuletti() || baseAccessRoles,
908
+ toLKA_A: this.isAgentAuletti() || baseAccessRoles,
909
+ toUU:
910
+ this.isJurist() ||
911
+ this.isDsuio() ||
912
+ this.isActuary() ||
913
+ this.isUSNSACCINS() ||
914
+ this.isServiceManager() ||
915
+ this.isAccountant() ||
916
+ this.isAdjuster() ||
917
+ this.isHeadAdjuster() ||
918
+ this.isArchivist() ||
919
+ this.isSecurity() ||
920
+ this.isUnderwriter() ||
921
+ this.isSanctioner1() ||
922
+ this.isSanctioner2() ||
923
+ this.isSanctioner3() ||
924
+ baseAccessRoles,
925
+ toReinsurance: this.isReInsurer() || this.isAdjuster() || this.isHeadAdjuster() || baseAccessRoles,
926
+ toReporting: this.isServiceManager() || this.isManager() || this.isSalesManager() || this.isChiefSalesManager() || this.isChiefManagerNSZH() || baseAccessRoles,
927
+ toDSO:
928
+ this.isUsns() ||
929
+ this.isDsuio() ||
930
+ this.isActuary() ||
931
+ this.isHeadOfDso() ||
932
+ this.isAccountant() ||
933
+ this.isUSNSACCINS() ||
934
+ this.isDsoDirector() ||
935
+ this.isNotAccumulativeSanctionerUSNS() ||
936
+ this.isServiceManager() ||
937
+ this.isUSNSsanctioner() ||
938
+ this.isAccountantDirector() ||
939
+ baseAccessRoles,
940
+ toEFO:
941
+ this.isAgentAuletti() ||
942
+ this.isManagerAuletti() ||
943
+ this.isManager() ||
944
+ this.isSalesManager() ||
945
+ this.isChiefSalesManager() ||
946
+ this.isChiefManagerNSZH() ||
947
+ this.isAgent() ||
948
+ this.isAgentMycar() ||
949
+ this.isManagerHalykBank() ||
950
+ this.isHeadManager() ||
951
+ this.isServiceManager() ||
952
+ this.isUSNSsanctioner() ||
953
+ this.isUnderwriter() ||
954
+ this.isActuary() ||
955
+ this.isCompliance() ||
956
+ this.isUpk() ||
957
+ this.isFinCenter() ||
958
+ this.isSupervisor() ||
959
+ this.isUrp() ||
960
+ this.isUsns() ||
961
+ this.isJurist() ||
962
+ this.isAccountant() ||
963
+ this.isBranchDirector() ||
964
+ this.isRegionDirector() ||
965
+ this.isUSNSACCINS() ||
966
+ this.isDsuio() ||
967
+ this.isAdjuster() ||
968
+ this.isDsoDirector() ||
969
+ this.isAccountantDirector() ||
970
+ this.isHeadAdjuster() ||
971
+ this.isHeadOfDso() ||
972
+ this.isUrsp() ||
973
+ this.isExecutor() ||
974
+ this.isArchivist() ||
975
+ this.isUKP() ||
976
+ this.isDpDirector() ||
977
+ this.isSecurity() ||
978
+ this.isURAP() ||
979
+ this.isTravelAgent() ||
980
+ this.isHR() ||
981
+ this.isNotAccumulativeSanctionerUSNS() ||
982
+ this.isReInsurer() ||
983
+ this.isSanctioner1() ||
984
+ this.isSanctioner2() ||
985
+ this.isSanctioner3() ||
986
+ baseAccessRoles,
987
+ };
988
+ };
989
+ }
990
+
991
+ /**
992
+ * Обрабатывает выход пользователя с очисткой данных
993
+ */
994
+ export function handleLogout() {
995
+ redirectUtils.clearRedirectUrl();
996
+ localStorage.removeItem('accessToken');
997
+ localStorage.removeItem('refreshToken');
998
+ }
999
+
1000
+ /**
1001
+ * Проверяет есть ли ожидающий redirect URL
1002
+ */
1003
+ export function checkPendingRedirect(): boolean {
1004
+ return !!localStorage.getItem('redirect_url');
1005
+ }
1006
+
1007
+ /**
1008
+ * Сохраняет текущую страницу перед переходом на авторизацию
1009
+ */
1010
+ export function saveCurrentPageBeforeAuth() {
1011
+ redirectUtils.saveCurrentUrl();
1012
+ }
1013
+
1014
+ /**
1015
+ * Утилиты для работы с redirect URL при авторизации
1016
+ */
1017
+ export const redirectUtils = {
1018
+ /**
1019
+ * Сохраняет текущий URL для возврата после авторизации
1020
+ */
1021
+ saveCurrentUrl(route?: any): void {
1022
+ let currentPath: string;
1023
+
1024
+ if (route && route.fullPath) {
1025
+ currentPath = route.fullPath;
1026
+ } else {
1027
+ currentPath = window.location.pathname + window.location.search;
1028
+ }
1029
+
1030
+ const excludedPaths = ['/auth', '/login', '/logout'];
1031
+
1032
+ console.log('Saving redirect URL:', currentPath);
1033
+
1034
+ if (!excludedPaths.some(path => currentPath.startsWith(path))) {
1035
+ localStorage.setItem('redirect_url', currentPath);
1036
+ console.log('Redirect URL saved:', currentPath);
1037
+ } else {
1038
+ console.log('URL excluded from redirect:', currentPath);
1039
+ }
1040
+ },
1041
+
1042
+ /**
1043
+ * Получает сохраненный URL и удаляет его из хранилища
1044
+ */
1045
+ getAndClearRedirectUrl(): string | null {
1046
+ const redirectUrl = localStorage.getItem('redirect_url');
1047
+ console.log('Getting redirect URL:', redirectUrl);
1048
+ if (redirectUrl) {
1049
+ localStorage.removeItem('redirect_url');
1050
+ console.log('Redirect URL cleared and returned:', redirectUrl);
1051
+ return redirectUrl;
1052
+ }
1053
+ console.log('No redirect URL found');
1054
+ return null;
1055
+ },
1056
+
1057
+ /**
1058
+ * Очищает сохраненный redirect URL
1059
+ */
1060
+ clearRedirectUrl(): void {
1061
+ localStorage.removeItem('redirect_url');
1062
+ },
1063
+
1064
+ /**
1065
+ * Получает сохраненный URL без удаления (для отладки)
1066
+ */
1067
+ getCurrentRedirectUrl(): string | null {
1068
+ return localStorage.getItem('redirect_url');
1069
+ },
1070
+ };
@@ -15,24 +15,13 @@ export class Styles {
15
15
  blueTextLight: string = 'text-[#F3F6FC]';
16
16
 
17
17
  // Green
18
- greenBg: string =
19
- import.meta.env.VITE_PRODUCT === 'auletti' || import.meta.env.VITE_PARENT_PRODUCT === 'auletti' || import.meta.env.VITE_PRODUCT === 'lka-auletti'
20
- ? 'bg-[#DEBE8C]'
21
- : 'bg-[#009C73]';
22
- greenBgHover: string =
23
- import.meta.env.VITE_PRODUCT === 'auletti' || import.meta.env.VITE_PARENT_PRODUCT === 'auletti' || import.meta.env.VITE_PRODUCT === 'lka-auletti'
24
- ? 'bg-[#C19B5F]'
25
- : 'hover:bg-[#00a277]';
26
- greenBgLight: string =
27
- import.meta.env.VITE_PRODUCT === 'auletti' || import.meta.env.VITE_PARENT_PRODUCT === 'auletti' || import.meta.env.VITE_PRODUCT === 'lka-auletti'
28
- ? 'bg-[#e8d2af]'
29
- : 'bg-[#EAF6EF]';
18
+ greenBg: string = String(import.meta.env.VITE_PRODUCT).includes('auletti') || import.meta.env.VITE_PARENT_PRODUCT === 'auletti' ? 'bg-[#DEBE8C]' : 'bg-[#009C73]';
19
+ greenBgHover: string = String(import.meta.env.VITE_PRODUCT).includes('auletti') || import.meta.env.VITE_PARENT_PRODUCT === 'auletti' ? 'bg-[#C19B5F]' : 'hover:bg-[#00a277]';
20
+ greenBgLight: string = String(import.meta.env.VITE_PRODUCT).includes('auletti') || import.meta.env.VITE_PARENT_PRODUCT === 'auletti' ? 'bg-[#e8d2af]' : 'bg-[#EAF6EF]';
30
21
  greenText: string = '!text-[#009C73]';
31
22
  greenTextHover: string = 'hover:text-[#009C73]';
32
23
  greenBgLightHover: string =
33
- import.meta.env.VITE_PRODUCT === 'auletti' || import.meta.env.VITE_PARENT_PRODUCT === 'auletti' || import.meta.env.VITE_PRODUCT === 'lka-auletti'
34
- ? 'hover:bg-[#efdfc6]'
35
- : 'hover:bg-[#dbf0e4]';
24
+ String(import.meta.env.VITE_PRODUCT).includes('auletti') || import.meta.env.VITE_PARENT_PRODUCT === 'auletti' ? 'hover:bg-[#efdfc6]' : 'hover:bg-[#dbf0e4]';
36
25
 
37
26
  // Yellow
38
27
  yellowText: string = '!text-[#FAB31C]';
@@ -65,7 +54,7 @@ export class Styles {
65
54
  blueBorder: string = 'border-[1px] border-[#A0B3D8]';
66
55
  blueLightBorder: string = 'border-[1px] border-[#F3F6FC]';
67
56
  greenBorder: string =
68
- import.meta.env.VITE_PRODUCT === 'auletti' || import.meta.env.VITE_PARENT_PRODUCT === 'auletti' || import.meta.env.VITE_PRODUCT === 'lka-auletti'
57
+ String(import.meta.env.VITE_PRODUCT).includes('auletti') || import.meta.env.VITE_PARENT_PRODUCT === 'auletti'
69
58
  ? 'border-[1px] border-[#DEBE8C]'
70
59
  : 'border-[1px] border-[#009C73]';
71
60
  redBorder: string = 'border-[1px] border-[#FD2D39]';
@@ -91,9 +80,9 @@ export class Styles {
91
80
  greenLightBtn: string;
92
81
 
93
82
  // Complex
94
- flexColNav: string;
95
- emptyBlockCol: string;
96
- scrollPage: string;
83
+ flexColNav: string = 'flex flex-col gap-[10px] px-2 pt-[14px]';
84
+ emptyBlockCol: string = 'w-[60px] sm:w-[100px] h-[30%] rounded-[8px] bg-[#f5f5f5]';
85
+ scrollPage: string = 'max-h-[85svh] overflow-y-scroll';
97
86
  flexCenter: string = 'flex items-center justify-center';
98
87
 
99
88
  // Muted or disabled
@@ -111,11 +100,6 @@ export class Styles {
111
100
  this.whiteBorderBtn = ` ${this.blackText} ${this.textTitle} ${this.rounded} w-full ${this.blueLightBgHover} border-[#A0B3D8] border-[1px]`;
112
101
  this.blueLightBtn = `${this.blueBgLight} ${this.greyTextLight} ${this.textTitle} ${this.rounded} w-full ${this.blueBgLightHover}`;
113
102
  this.greenLightBtn = `${this.greenBgLight} ${this.greenText} ${this.textTitle} ${this.rounded} w-full ${this.greenBgLightHover}`;
114
-
115
- // Complex
116
- this.flexColNav = 'flex flex-col gap-[10px] px-2 pt-[14px]';
117
- this.emptyBlockCol = 'w-[60px] sm:w-[100px] h-[30%] rounded-[8px] bg-[#f5f5f5]';
118
- this.scrollPage = 'max-h-[85svh] overflow-y-scroll';
119
103
  }
120
104
  }
121
105
 
package/configs/i18n.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { createI18n } from 'vue-i18n';
2
2
  import ru from '../locales/ru.json';
3
+ import kz from '../locales/kz.json';
3
4
 
4
5
  const instance = createI18n({
5
6
  legacy: false,
@@ -7,6 +8,7 @@ const instance = createI18n({
7
8
  locale: 'ru',
8
9
  messages: {
9
10
  ru,
11
+ kz,
10
12
  },
11
13
  });
12
14
 
package/configs/pwa.ts CHANGED
@@ -3,7 +3,7 @@ import type { ModuleOptions } from '@vite-pwa/nuxt';
3
3
  export const pwaBaseConfig: Partial<ModuleOptions> = {
4
4
  registerType: 'autoUpdate',
5
5
  workbox: {
6
- globPatterns: ['**/*.{js,css,html,txt,png,ico,svg}'],
6
+ globPatterns: ['**/*.{js,css,html,txt,png,ico,svg,json}'],
7
7
  navigateFallbackDenylist: [/^\/api\//],
8
8
  navigateFallback: '/',
9
9
  cleanupOutdatedCaches: true,
@@ -54,10 +54,4 @@ export const pwaBaseConfig: Partial<ModuleOptions> = {
54
54
  },
55
55
  registerWebManifestInRouteRules: true,
56
56
  writePlugin: true,
57
- devOptions: {
58
- enabled: true,
59
- suppressWarnings: true,
60
- navigateFallback: '/',
61
- type: 'module',
62
- },
63
57
  };
package/layouts/clear.vue CHANGED
@@ -8,7 +8,7 @@ const { $pwa } = useNuxtApp();
8
8
 
9
9
  const onInit = async () => {
10
10
  const projectConfig = dataStore.projectConfig;
11
- if (!useEnv().isProduction && process.env.NODE_ENV === 'production' && $pwa && projectConfig === null) {
11
+ if (process.env.NODE_ENV === 'production' && $pwa && projectConfig === null) {
12
12
  const hasConfig = await dataStore.getProjectConfig();
13
13
  if (hasConfig === true) {
14
14
  const commitVersion = String(import.meta.env.VITE_COMMIT_VERSION);