hl-core 0.0.7-beta.2 → 0.0.7-beta.21

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 (57) hide show
  1. package/.prettierrc +2 -1
  2. package/api/index.ts +323 -31
  3. package/api/interceptors.ts +10 -1
  4. package/components/Button/Btn.vue +7 -2
  5. package/components/Button/BtnIcon.vue +47 -0
  6. package/components/Button/ScrollButtons.vue +6 -0
  7. package/components/Complex/Content.vue +1 -1
  8. package/components/Complex/ContentBlock.vue +5 -0
  9. package/components/Complex/Page.vue +13 -2
  10. package/components/{Layout → Dialog}/Dialog.vue +7 -11
  11. package/components/Dialog/FamilyDialog.vue +39 -0
  12. package/components/Form/FormBlock.vue +114 -0
  13. package/components/Form/FormSection.vue +18 -0
  14. package/components/Form/FormTextSection.vue +20 -0
  15. package/components/Form/FormToggle.vue +52 -0
  16. package/components/Form/ProductConditionsBlock.vue +68 -0
  17. package/components/Input/EmptyFormField.vue +5 -0
  18. package/components/Input/FileInput.vue +71 -0
  19. package/components/Input/FormInput.vue +171 -0
  20. package/components/Input/PanelInput.vue +133 -0
  21. package/components/Input/RoundedInput.vue +40 -36
  22. package/components/Layout/Drawer.vue +44 -0
  23. package/components/Layout/Header.vue +26 -12
  24. package/components/Layout/Loader.vue +9 -6
  25. package/components/Layout/SettingsPanel.vue +48 -0
  26. package/components/List/ListEmpty.vue +22 -0
  27. package/components/Menu/MenuNav.vue +70 -30
  28. package/components/Menu/MenuNavItem.vue +8 -1
  29. package/components/Pages/Anketa.vue +333 -0
  30. package/components/Pages/Auth.vue +91 -0
  31. package/components/Pages/Documents.vue +108 -0
  32. package/components/Pages/MemberForm.vue +1138 -0
  33. package/components/Pages/ProductAgreement.vue +18 -0
  34. package/components/Pages/ProductConditions.vue +349 -0
  35. package/components/Panel/PanelItem.vue +5 -0
  36. package/components/Panel/PanelSelectItem.vue +20 -0
  37. package/components/Transitions/FadeTransition.vue +5 -0
  38. package/composables/classes.ts +413 -207
  39. package/composables/constants.ts +27 -12
  40. package/composables/index.ts +73 -35
  41. package/composables/styles.ts +31 -7
  42. package/layouts/clear.vue +1 -1
  43. package/layouts/default.vue +72 -6
  44. package/layouts/full.vue +6 -0
  45. package/nuxt.config.ts +5 -2
  46. package/package.json +17 -11
  47. package/pages/500.vue +85 -0
  48. package/plugins/helperFunctionsPlugins.ts +10 -2
  49. package/plugins/storePlugin.ts +6 -5
  50. package/store/data.store.js +1858 -527
  51. package/store/member.store.ts +291 -0
  52. package/store/messages.ts +152 -34
  53. package/store/rules.js +26 -28
  54. package/tailwind.config.js +10 -0
  55. package/types/index.ts +250 -0
  56. package/models/index.ts +0 -23
  57. /package/store/{form.store.js → form.store.ts} +0 -0
@@ -0,0 +1,133 @@
1
+ <template>
2
+ <v-text-field
3
+ class="form-input"
4
+ :model-value="modelValue"
5
+ v-maska="maska"
6
+ :rules="rules"
7
+ :loading="loading"
8
+ :placeholder="placeholder"
9
+ :label="label"
10
+ :messages="messages"
11
+ :type="type"
12
+ :variant="variant"
13
+ :clear-icon="clearIcon"
14
+ :color="color"
15
+ :hint="hint"
16
+ :clearable="clearable"
17
+ :disabled="disabled"
18
+ :readonly="true"
19
+ :prepend-icon="prependIcon ? prependIcon : ''"
20
+ :append-icon="appendIcon ? appendIcon : ''"
21
+ :prepend-inner-icon="prependInnerIcon ? prependInnerIcon : ''"
22
+ :append-inner-icon="appendInnerIcon ? appendInnerIcon : ''"
23
+ :bg-color="bgColor ? bgColor : ''"
24
+ @keyup.enter.prevent="submitted"
25
+ @click:control="!props.readonly && $emit('append')"
26
+ @click:clear="(props.readonly ? false : clearable) && $emit('update:modelValue', new Value())"
27
+ @click:append="!props.readonly && $emit('append-out')"
28
+ @click:prepend="!props.readonly && $emit('prepend-out')"
29
+ @click:append-inner="!props.readonly && $emit('append')"
30
+ @click:prepend-inner="!props.readonly && $emit('prepend')"
31
+ @update:modelValue="$emit('update:modelValue', $event)"
32
+ >
33
+ <template v-if="loading" #loader>
34
+ <v-progress-linear :active="loading" :color="color" absolute height="1" indeterminate></v-progress-linear>
35
+ </template>
36
+ </v-text-field>
37
+ </template>
38
+
39
+ <script lang="ts">
40
+ import { Value } from '@/composables/classes';
41
+
42
+ export default defineComponent({
43
+ name: 'BasePanelInput',
44
+ props: {
45
+ modelValue: {
46
+ required: false,
47
+ },
48
+ loading: {
49
+ type: Boolean,
50
+ default: false,
51
+ },
52
+ clearable: {
53
+ type: Boolean,
54
+ default: true,
55
+ },
56
+ disabled: {
57
+ type: Boolean,
58
+ default: false,
59
+ },
60
+ readonly: {
61
+ type: Boolean,
62
+ default: false,
63
+ },
64
+ placeholder: {
65
+ type: String,
66
+ default: '',
67
+ },
68
+ label: {
69
+ type: String,
70
+ default: '',
71
+ },
72
+ messages: {
73
+ type: [String, Array<string>],
74
+ },
75
+ maska: {
76
+ type: String,
77
+ default: '',
78
+ },
79
+ hint: {
80
+ type: String,
81
+ default: '',
82
+ },
83
+ rules: {
84
+ type: Array<any>,
85
+ default: [],
86
+ },
87
+ type: {
88
+ type: String as PropType<InputTypes>,
89
+ default: 'text',
90
+ },
91
+ variant: {
92
+ type: String as PropType<InputVariants>,
93
+ default: 'solo',
94
+ },
95
+ color: {
96
+ type: String,
97
+ default: '#009c73',
98
+ },
99
+ clearIcon: {
100
+ type: String,
101
+ default: 'mdi-close',
102
+ },
103
+ prependIcon: {
104
+ type: String,
105
+ },
106
+ appendIcon: {
107
+ type: String,
108
+ },
109
+ prependInnerIcon: {
110
+ type: String,
111
+ },
112
+ appendInnerIcon: {
113
+ type: String,
114
+ },
115
+ bgColor: {
116
+ type: String,
117
+ },
118
+ },
119
+ emits: ['update:modelValue', 'submitted', 'prepend', 'append', 'prepend-out', 'append-out', 'clear'],
120
+
121
+ setup(props, { emit }) {
122
+ const submitted = (event: any) => {
123
+ emit('submitted', event);
124
+ };
125
+
126
+ return {
127
+ submitted,
128
+ Value,
129
+ props,
130
+ };
131
+ },
132
+ });
133
+ </script>
@@ -1,43 +1,44 @@
1
1
  <template>
2
2
  <v-text-field
3
3
  class="rounded-input"
4
- v-model="fieldModel"
4
+ :model-value="modelValue"
5
+ v-maska="maska"
5
6
  :rules="rules"
6
7
  :loading="loading"
7
8
  :placeholder="placeholder"
9
+ :label="label"
8
10
  :type="type"
9
11
  :variant="variant"
10
12
  :clear-icon="clearIcon"
11
13
  :color="color"
12
14
  :hint="hint"
13
- :clearable="clearable"
15
+ :clearable="props.readonly ? false : clearable"
14
16
  :disabled="disabled"
15
- :prepend-inner-icon="prependIcon ? prependIcon : ''"
17
+ :readonly="props.readonly"
18
+ :prepend-icon="prependIcon ? prependIcon : ''"
16
19
  :append-icon="appendIcon ? appendIcon : ''"
20
+ :prepend-inner-icon="prependInnerIcon ? prependInnerIcon : ''"
21
+ :append-inner-icon="appendInnerIcon ? appendInnerIcon : ''"
17
22
  :bg-color="bgColor ? bgColor : ''"
18
23
  @keyup.enter.prevent="submitted"
24
+ @click:append="!props.readonly && $emit('append-out')"
25
+ @click:prepend="!props.readonly && $emit('prepend-out')"
26
+ @click:append-inner="!props.readonly && $emit('append')"
27
+ @click:prepend-inner="!props.readonly && $emit('prepend')"
28
+ @update:modelValue="$emit('update:modelValue', $event)"
19
29
  >
20
30
  <template v-if="loading" #loader>
21
- <v-progress-linear
22
- :active="loading"
23
- :color="color"
24
- absolute
25
- height="1"
26
- indeterminate
27
- ></v-progress-linear>
31
+ <v-progress-linear :active="loading" :color="color" absolute height="1" indeterminate></v-progress-linear>
28
32
  </template>
29
33
  </v-text-field>
30
34
  </template>
31
35
 
32
36
  <script lang="ts">
33
- import { InputTypes } from '@/models';
34
-
35
37
  export default defineComponent({
36
38
  name: 'BaseRoundedInput',
37
39
  props: {
38
40
  modelValue: {
39
- type: String,
40
- default: '',
41
+ required: false,
41
42
  },
42
43
  loading: {
43
44
  type: Boolean,
@@ -51,9 +52,21 @@ export default defineComponent({
51
52
  type: Boolean,
52
53
  default: false,
53
54
  },
55
+ readonly: {
56
+ type: Boolean,
57
+ default: false,
58
+ },
54
59
  placeholder: {
55
60
  type: String,
56
- default: 'Поле',
61
+ default: '',
62
+ },
63
+ label: {
64
+ type: String,
65
+ default: '',
66
+ },
67
+ maska: {
68
+ type: String,
69
+ default: '',
57
70
  },
58
71
  hint: {
59
72
  type: String,
@@ -68,9 +81,7 @@ export default defineComponent({
68
81
  default: 'text',
69
82
  },
70
83
  variant: {
71
- type: String as PropType<
72
- 'solo' | 'filled' | 'outlined' | 'plain' | 'underlined'
73
- >,
84
+ type: String as PropType<InputVariants>,
74
85
  default: 'solo',
75
86
  },
76
87
  color: {
@@ -87,34 +98,26 @@ export default defineComponent({
87
98
  appendIcon: {
88
99
  type: String,
89
100
  },
101
+ prependInnerIcon: {
102
+ type: String,
103
+ },
104
+ appendInnerIcon: {
105
+ type: String,
106
+ },
90
107
  bgColor: {
91
108
  type: String,
92
109
  },
93
110
  },
94
- emits: ['update:modelValue', 'submitted'],
111
+ emits: ['update:modelValue', 'submitted', 'prepend', 'append', 'prepend-out', 'append-out'],
95
112
 
96
113
  setup(props, { emit }) {
97
- const fieldModel = ref(props.modelValue || '');
98
-
99
- const updateValue = (event: any) => {
100
- emit('update:modelValue', fieldModel.value);
101
- };
102
-
103
114
  const submitted = (event: any) => {
104
115
  emit('submitted', event);
105
116
  };
106
117
 
107
- watch(
108
- fieldModel,
109
- () => {
110
- updateValue(fieldModel.value);
111
- },
112
- { immediate: true },
113
- );
114
-
115
118
  return {
116
- fieldModel,
117
119
  submitted,
120
+ props
118
121
  };
119
122
  },
120
123
  });
@@ -125,14 +128,15 @@ export default defineComponent({
125
128
  border: none !important;
126
129
  outline: none !important;
127
130
  }
128
-
131
+ .rounded-input .v-label.v-field-label {
132
+ top: 20px;
133
+ }
129
134
  .rounded-input .v-field {
130
135
  border-radius: 8px;
131
136
  border: 1px solid #dadada;
132
137
  box-shadow: none;
133
138
  font-size: 14px;
134
139
  }
135
-
136
140
  .rounded-input .v-field--error {
137
141
  border-color: #ff5449;
138
142
  }
@@ -0,0 +1,44 @@
1
+ <template>
2
+ <v-navigation-drawer
3
+ v-model="$dataStore[whichPanel].open"
4
+ :temporary="$dataStore[whichPanel].overlay"
5
+ location="right"
6
+ class="sm:!w-[400px] lg:!relative !right-0"
7
+ :class="[$dataStore[whichPanel].overlay ? 'lg:!hidden' : '', $dataStore[whichPanel].open ? '!w-full lg:!w-[420px]' : 'lg:!w-[0px]']"
8
+ :disable-resize-watcher="true"
9
+ :disable-route-watcher="true"
10
+ >
11
+ <base-header :title="panelTitle" :has-back="true" back-icon="mdi-close" class="justify-center" @onBack="closePanel"></base-header>
12
+ <div class="flex flex-col" :id="$dataStore.panelAction === null ? 'panel-actions' : ''">
13
+ <slot></slot>
14
+ </div>
15
+ </v-navigation-drawer>
16
+ </template>
17
+
18
+ <script lang="ts">
19
+ export default defineComponent({
20
+ name: 'BasePanel',
21
+ props: {
22
+ panelTitle: {
23
+ type: String,
24
+ default: '',
25
+ },
26
+ whichPanel: {
27
+ type: String as PropType<PanelTypes>,
28
+ default: 'panel',
29
+ },
30
+ },
31
+ setup(props) {
32
+ const dataStore = useDataStore();
33
+
34
+ const closePanel = () => {
35
+ dataStore[props.whichPanel].open = false;
36
+ dataStore.panelAction = null;
37
+ };
38
+
39
+ return {
40
+ closePanel,
41
+ };
42
+ },
43
+ });
44
+ </script>
@@ -1,15 +1,8 @@
1
1
  <template>
2
- <header
3
- class="relative w-full h-[70px] text-center font-medium align-middle flex items-center border-b-[1px]"
4
- :class="[$libStyles.blueBgLight, $libStyles.textSimple]"
5
- >
6
- <i
7
- v-if="hasBack"
8
- @click="$emit('onBack')"
9
- class="absolute left-5 mdi text-lg cursor-pointer"
10
- :class="[backIcon]"
11
- ></i>
12
- {{ title }}
2
+ <header class="relative w-full h-[70px] text-center font-medium align-middle flex items-center border-b-[1px]" :class="[$libStyles.blueBgLight, $libStyles.textSimple]">
3
+ <i v-if="hasBack" @click="$emit('onBack')" class="absolute left-5 mdi text-xl cursor-pointer" :class="[backIcon]"></i>
4
+ <span class="mx-10">{{ title }}</span>
5
+ <i v-if="hasMore" @click="$emit('onMore')" class="mdi absolute right-5 text-xl cursor-pointer" :class="[moreIcon, hideMoreOnLg ? 'lg:!hidden' : '']"> </i>
13
6
  </header>
14
7
  </template>
15
8
 
@@ -20,15 +13,36 @@ export default defineComponent({
20
13
  type: Boolean,
21
14
  default: false,
22
15
  },
16
+ hasMore: {
17
+ type: Boolean,
18
+ default: false,
19
+ },
20
+ hideMoreOnLg: {
21
+ type: Boolean,
22
+ default: false,
23
+ },
23
24
  backIcon: {
24
25
  type: String,
25
26
  default: 'mdi-arrow-left',
26
27
  },
28
+ moreIcon: {
29
+ type: String,
30
+ default: 'mdi-cog-outline',
31
+ },
27
32
  title: {
28
33
  type: String,
29
34
  default: '',
30
35
  },
31
36
  },
32
- emits: ['onBack'],
37
+ emits: ['onBack', 'onMore'],
38
+ setup() {
39
+ const dataStore = useDataStore();
40
+
41
+ const onClickOutside = () => {
42
+ dataStore.settings.open = false;
43
+ };
44
+
45
+ return { onClickOutside };
46
+ },
33
47
  });
34
48
  </script>
@@ -1,10 +1,5 @@
1
1
  <template>
2
- <v-progress-circular
3
- :size="size"
4
- :indeterminate="indeterminate"
5
- :color="color"
6
- :bg-color="bgColor"
7
- ></v-progress-circular>
2
+ <v-progress-circular :size="size" :width="width" :indeterminate="indeterminate" :color="color" :bg-color="bgColor"></v-progress-circular>
8
3
  </template>
9
4
 
10
5
  <script lang="ts">
@@ -15,10 +10,18 @@ export default defineComponent({
15
10
  type: Number,
16
11
  default: 40,
17
12
  },
13
+ width: {
14
+ type: Number,
15
+ default: 4,
16
+ },
18
17
  indeterminate: {
19
18
  type: Boolean,
20
19
  default: true,
21
20
  },
21
+ overlay: {
22
+ type: Boolean,
23
+ default: true,
24
+ },
22
25
  color: {
23
26
  type: String,
24
27
  default: '#FAB31C',
@@ -0,0 +1,48 @@
1
+ <template>
2
+ <base-drawer :panel-title="$dataStore.menu.title" which-panel="settings">
3
+ <base-panel-item>
4
+ <v-btn size="x-small" icon="mdi-minus" color="#A0B3D8" class="text-white" variant="flat" @click="handleFontSize('decrease')"></v-btn>
5
+ Шрифт
6
+ <v-btn size="x-small" icon="mdi-plus" color="#A0B3D8" class="text-white" variant="flat" @click="handleFontSize('increase')"></v-btn>
7
+ </base-panel-item>
8
+ <base-panel-item>
9
+ <v-text-field v-model="$dataStore.user.fullName" :readonly="true" hide-details variant="plain" :label="$dataStore.user.roles?.join(', ')"></v-text-field>
10
+ <i class="mdi mdi-account-outline text-2xl text-[#A0B3D8]"></i
11
+ ></base-panel-item>
12
+ <base-panel-item
13
+ v-for="panelItem of dataStore.settings.items.filter(i => (typeof i.show === 'boolean' ? i.show : true))"
14
+ :key="panelItem.title!"
15
+ class="cursor-pointer"
16
+ @click="panelItem.action ? panelItem.action() : null"
17
+ >
18
+ {{ panelItem.title }}
19
+ <i v-if="panelItem.icon" class="mdi text-xl text-[#A0B3D8]" :class="[panelItem.icon]"></i>
20
+ </base-panel-item>
21
+ <base-panel-item @click="dialog = true" class="cursor-pointer">
22
+ Выход
23
+ <i class="mdi mdi-logout text-xl text-[#A0B3D8]"></i>
24
+ </base-panel-item>
25
+
26
+ <base-dialog v-model="dialog" :title="$t('dialog.exit')" :subtitle="$t('dialog.dataWillClear')" actions="default" @yes="logoutUser" @no="dialog = false"> </base-dialog
27
+ ></base-drawer>
28
+ </template>
29
+
30
+ <script lang="ts" setup>
31
+ const dialog = ref(false);
32
+ const dataStore = useDataStore();
33
+
34
+ const handleFontSize = (action: 'increase' | 'decrease') => {
35
+ if (action === 'increase' && dataStore.fontSize < 24) dataStore.fontSize += 2;
36
+ if (action === 'decrease' && dataStore.fontSize > 14) dataStore.fontSize -= 2;
37
+ if (dataStore.isEFO) {
38
+ dataStore.sendToChild(constants.postActions.font, dataStore.fontSize);
39
+ } else {
40
+ dataStore.sendToParent(constants.postActions.font, dataStore.fontSize);
41
+ }
42
+ };
43
+
44
+ const logoutUser = async () => {
45
+ dialog.value = false;
46
+ await dataStore.logoutUser();
47
+ };
48
+ </script>
@@ -0,0 +1,22 @@
1
+ <template>
2
+ <div class="border-[1px] rounded-lg h-[80px] mx-[10px] mt-[14px] flex place-content-center" :class="[$libStyles.blueBgLight, $libStyles.textTitle]">
3
+ <div class="flex justify-center items-center font-medium gap-2 opacity-40">
4
+ {{ text }}
5
+ <i class="text-2xl mdi" :class="[icon ? icon : 'mdi-database-off-outline']"></i>
6
+ </div>
7
+ </div>
8
+ </template>
9
+
10
+ <script lang="ts">
11
+ export default defineComponent({
12
+ props: {
13
+ text: {
14
+ type: String,
15
+ default: 'Отсутствуют данные',
16
+ },
17
+ icon: {
18
+ type: String,
19
+ },
20
+ },
21
+ });
22
+ </script>
@@ -1,37 +1,51 @@
1
1
  <template>
2
- <aside class="w-full lg:w-1/4 bg-white flex flex-col border-r-2">
2
+ <aside class="w-full lg:w-1/4 bg-white flex flex-col border-r-2 relative">
3
3
  <base-header
4
4
  class="justify-center"
5
5
  :title="title"
6
6
  :has-back="hasBack"
7
7
  :back-icon="backIcon"
8
+ :has-more="hasMore"
9
+ :hide-more-on-lg="hideMoreOnLg"
10
+ :more-icon="moreIcon"
8
11
  @onBack="$emit('onBack')"
12
+ @onMore="$emit('onMore')"
9
13
  ></base-header>
10
- <transition-group enter-active-class="animate__animated animate__fadeIn">
11
- <slot name="content"></slot>
12
- <section
13
- v-if="items && items.length"
14
- class="px-2 pt-[14px] flex flex-col gap-[10px]"
15
- >
16
- <slot name="start"></slot>
17
- <base-menu-nav-item
18
- v-for="(item, index) of items"
19
- :key="index"
20
- :menu-item="item"
21
- :selected="
22
- selected.title && item.title && selected.title === item.title
23
- "
24
- @click="pickItem(item)"
25
- >
26
- </base-menu-nav-item>
27
- <slot name="end"></slot>
28
- </section>
29
- </transition-group>
14
+ <slot key="slot-content" name="content"></slot>
15
+ <section key="main" :class="[$libStyles.flexColNav]">
16
+ <slot name="start"></slot>
17
+ <base-fade-transition>
18
+ <div v-if="$dataStore.menuItems && $dataStore.menuItems.length" class="flex flex-col gap-[10px]">
19
+ <div v-for="(item, index) of $dataStore.menuItems.filter(i => (typeof i.show === 'boolean' ? i.show : true))" :key="index">
20
+ <base-menu-nav-item
21
+ :menu-item="item"
22
+ :selected="!!selected.title && !!item.title && selected.title === item.title"
23
+ :disabled="typeof item.disabled === 'boolean' ? item.disabled : false"
24
+ @click.left="pickItem(item)"
25
+ @click.middle="openTab(item)"
26
+ >
27
+ </base-menu-nav-item>
28
+ <hr v-if="item.hasLine" class="mt-[10px]" />
29
+ </div>
30
+ </div>
31
+ </base-fade-transition>
32
+ <slot name="end"></slot>
33
+ <slot name="actions"></slot>
34
+ <base-fade-transition>
35
+ <div v-if="$dataStore.buttons && $dataStore.buttons.length" class="flex flex-col gap-[10px] justify-self-end absolute bottom-5 lg:bottom-[30%] w-full pr-4">
36
+ <div v-for="(item, index) of $dataStore.buttons" :key="index">
37
+ <transition enter-active-class="animate__animated animate__fadeIn animate__faster" leave-active-class="animate__animated animate__fadeOut animate__faster">
38
+ <base-btn v-if="'show' in item ? item.show : true" :text="item.title!" :btn="item.color" :disabled="item.disabled" @click="item.action"> </base-btn>
39
+ </transition>
40
+ </div></div
41
+ ></base-fade-transition>
42
+ </section>
30
43
  </aside>
31
44
  </template>
32
45
 
33
46
  <script lang="ts">
34
47
  import { MenuItem } from '@/composables/classes';
48
+ import { RouteLocationNormalized } from 'vue-router';
35
49
 
36
50
  export default defineComponent({
37
51
  props: {
@@ -39,10 +53,6 @@ export default defineComponent({
39
53
  type: String,
40
54
  default: 'Заголовок',
41
55
  },
42
- items: {
43
- type: Array<MenuItem>,
44
- default: [],
45
- },
46
56
  selected: {
47
57
  type: Object as PropType<MenuItem>,
48
58
  default: new MenuItem(),
@@ -55,14 +65,44 @@ export default defineComponent({
55
65
  type: String,
56
66
  default: 'mdi-arrow-left',
57
67
  },
68
+ hasMore: {
69
+ type: Boolean,
70
+ default: false,
71
+ },
72
+ hideMoreOnLg: {
73
+ type: Boolean,
74
+ default: false,
75
+ },
76
+ moreIcon: {
77
+ type: String,
78
+ default: 'mdi-cog-outline',
79
+ },
58
80
  },
59
- emits: ['update:modelValue', 'onLink', 'onBack', 'clicked'],
81
+ emits: ['onLink', 'onBack', 'onMore', 'clicked'],
60
82
  setup(props, { emit }) {
61
- const pickItem = (item: MenuItem) => {
62
- emit('update:modelValue', item);
63
- item.link ? emit('onLink', item) : emit('clicked', item);
83
+ const dataStore = useDataStore();
84
+ const router = useRouter();
85
+
86
+ const pickItem = async (item: MenuItem) => {
87
+ if (item.title !== dataStore.menu.selectedItem.title && (typeof item.disabled === 'boolean' ? !item.disabled : true)) {
88
+ if (typeof item.link === 'object') {
89
+ if (item.link && 'name' in item.link) {
90
+ await router.push(item.link as RouteLocationNormalized);
91
+ } else {
92
+ dataStore.showToaster('warning', 'Отсутствует ссылка для перехода');
93
+ }
94
+ } else {
95
+ emit('onLink', item);
96
+ }
97
+ }
98
+ };
99
+ const openTab = (item: MenuItem) => {
100
+ if (item.url) {
101
+ window.open(item.url, '_blank', 'noreferrer');
102
+ }
64
103
  };
65
- return { pickItem };
104
+
105
+ return { pickItem, openTab };
66
106
  },
67
107
  });
68
108
  </script>
@@ -5,10 +5,13 @@
5
5
  selected ? $libStyles.whiteText : $libStyles.blackText,
6
6
  $libStyles.rounded,
7
7
  $libStyles.textSimple,
8
+ disabled ? 'cursor-not-allowed opacity-50' : '',
8
9
  ]"
9
- class="h-[60px] flex items-center hover:bg-[#A0B3D8] hover:!text-white pl-4 cursor-pointer transition-all"
10
+ class="h-[60px] flex items-center justify-between hover:bg-[#A0B3D8] hover:!text-white pl-4 cursor-pointer transition-all"
10
11
  >
11
12
  <span>{{ menuItem.title }}</span>
13
+ <i v-if="menuItem.icon" class="mdi text-xl pr-4" :class="[menuItem.icon]"></i>
14
+ <v-tooltip v-if="menuItem.description" activator="parent" location="bottom">{{ menuItem.description }}</v-tooltip>
12
15
  </div>
13
16
  </template>
14
17
 
@@ -25,6 +28,10 @@ export default defineComponent({
25
28
  type: Boolean,
26
29
  default: false,
27
30
  },
31
+ disabled: {
32
+ type: Boolean,
33
+ default: false,
34
+ },
28
35
  },
29
36
  });
30
37
  </script>