adata-ui 2.1.38 → 2.1.40-beta
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.
- package/.nuxtrc +1 -1
- package/.playground/app.config.ts +5 -5
- package/.playground/app.vue +102 -0
- package/README.md +75 -75
- package/components/elements/README.md +1 -1
- package/components/elements/button-login/index.vue +6 -10
- package/components/elements/tree-select/ATreeSelect.vue +5 -1
- package/components/elements/tree-select/components/tree-select-nodes.vue +4 -3
- package/components/features/color-mode/AColorMode.client.vue +74 -32
- package/components/features/dropdown/ADropdownV2.vue +141 -0
- package/components/features/lang-switcher/lang-switcher.vue +120 -40
- package/components/features//321/201hange-version/AChangeVersion.vue +1 -1
- package/components/forms/README.md +1 -1
- package/components/navigation/README.md +1 -1
- package/components/navigation/footer/AFooter.vue +1 -1
- package/components/navigation/header/AHeader.vue +56 -33
- package/components/navigation/header/AlmatyContacts.vue +1 -1
- package/components/navigation/header/CardGallery.vue +5 -3
- package/components/navigation/header/ContactMenu.vue +26 -92
- package/components/navigation/header/HeaderLink.vue +189 -215
- package/components/navigation/header/HeaderUsage.vue +125 -0
- package/components/navigation/header/NavList.vue +35 -50
- package/components/navigation/header/ProductMenu.vue +72 -126
- package/components/navigation/header/ProfileMenu.vue +131 -150
- package/components/navigation/header/SystemNotification.vue +110 -0
- package/components/navigation/mobile-navigation/AMobileNavigation.vue +23 -15
- package/components/navigation/pill-tabs/APillTabs.vue +7 -2
- package/components/overlays/README.md +1 -1
- package/components/overlays/tooltip/ATooltipV2.vue +233 -0
- package/components/overlays/tooltip/types.ts +26 -0
- package/components/overlays/tooltip/useTooltipTrigger.ts +101 -0
- package/composables/useHeaderNavigationLinks.ts +15 -8
- package/composables/useUrls.ts +1 -1
- package/icons/gauge.vue +17 -0
- package/icons/sun.vue +13 -3
- package/lang/en.ts +6 -0
- package/lang/kk.ts +6 -0
- package/lang/ru.ts +6 -0
- package/package.json +1 -1
- package/shared/constans/pages.ts +1 -1
- package/components/navigation/header/TopHeader.vue +0 -196
|
@@ -1,195 +1,176 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useHeaderMenuLinks } from '#adata-ui/composables/useHeaderNavigationLinks'
|
|
3
|
+
import Calendar from '#adata-ui/icons/calendar.vue'
|
|
4
|
+
import Gauge from '#adata-ui/icons/gauge.vue'
|
|
2
5
|
import IconLogout from '#adata-ui/icons/logout.vue'
|
|
3
6
|
import { useMediaQuery } from '@vueuse/core'
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
|
|
8
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
9
|
+
daysRemaining: 0,
|
|
10
|
+
limitRemaining: 0,
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
defineEmits(['logout'])
|
|
6
14
|
|
|
7
15
|
const isLargeScreen = useMediaQuery('(min-width: 1024px)')
|
|
8
16
|
|
|
9
17
|
interface Props {
|
|
10
18
|
rate: string
|
|
11
|
-
daysRemaining
|
|
12
|
-
limitRemaining
|
|
19
|
+
daysRemaining?: number
|
|
20
|
+
limitRemaining?: number
|
|
13
21
|
balance: number
|
|
22
|
+
email?: string
|
|
14
23
|
replenish?: string
|
|
15
24
|
oldVersion?: string
|
|
16
25
|
}
|
|
17
26
|
|
|
18
|
-
const
|
|
19
|
-
daysRemaining: 0,
|
|
20
|
-
limitRemaining: 0
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
defineEmits(['logout'])
|
|
27
|
+
const formattedBalance = computed(() => props.balance.toLocaleString('ru-RU'))
|
|
24
28
|
|
|
25
29
|
const { t } = useI18n()
|
|
26
30
|
|
|
27
|
-
const { locale } = useI18n()
|
|
28
|
-
|
|
29
|
-
// const { topUpSidePanel } = usePayment()
|
|
30
|
-
|
|
31
31
|
const items = useHeaderMenuLinks()
|
|
32
32
|
|
|
33
33
|
const { topUpSidePanel, rateId } = usePayment()
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
// if (myLayer.authMode === 'locale') {
|
|
37
|
-
// topUpSidePanel.value = true
|
|
38
|
-
// return
|
|
39
|
-
// }
|
|
35
|
+
function onReplenish() {
|
|
40
36
|
rateId.value = ''
|
|
41
37
|
topUpSidePanel.value = true
|
|
42
38
|
}
|
|
43
39
|
</script>
|
|
44
40
|
|
|
45
41
|
<template>
|
|
46
|
-
<div class="
|
|
47
|
-
<!--
|
|
48
|
-
<div
|
|
49
|
-
class="
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class="
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
{{ t('header.profile.currentBalance') }}
|
|
70
|
-
<span class="ml-2 rounded-xl bg-deepblue-900 px-2 py-1">{{ balance.toLocaleString('RU-ru') }} ₸</span>
|
|
71
|
-
</div>
|
|
72
|
-
<a-button
|
|
73
|
-
size="sm"
|
|
74
|
-
class="w-full mt-4"
|
|
75
|
-
view="outline"
|
|
76
|
-
variant="ghost"
|
|
77
|
-
@click="onReplenish"
|
|
78
|
-
>
|
|
79
|
-
<a-icon-plus-circle />
|
|
80
|
-
{{ t('header.profile.addBalance') }}
|
|
81
|
-
</a-button>
|
|
82
|
-
</div>
|
|
83
|
-
</div>
|
|
84
|
-
<!-- mobile -->
|
|
85
|
-
<div class="gradient-bg px-4 py-4 text-white dark:text-gray-900 lg:hidden">
|
|
86
|
-
<div class="flex justify-between gap-4 lg:mt-2">
|
|
87
|
-
<div class="flex flex-col items-center">
|
|
88
|
-
<div class="font-semibold">
|
|
89
|
-
{{ rate }}
|
|
42
|
+
<div class="w-full overflow-hidden bg-white text-deepblue-900 dark:bg-gray-900 dark:text-gray-200 lg:w-[320px] lg:rounded-xl lg:border lg:border-gray-200 lg:dark:border-gray-800">
|
|
43
|
+
<!-- Subscription & balance card -->
|
|
44
|
+
<div class="p-2">
|
|
45
|
+
<div class="relative overflow-hidden rounded-xl bg-gradient-to-br from-blue-700/95 to-blue-500/85 p-3 text-white">
|
|
46
|
+
<!-- decorative glow for a "living" feel -->
|
|
47
|
+
<div class="pointer-events-none absolute -right-8 -top-10 size-28 rounded-full bg-white/20 blur-2xl" aria-hidden="true" />
|
|
48
|
+
|
|
49
|
+
<div class="relative">
|
|
50
|
+
<!-- Tariff -->
|
|
51
|
+
<p class="text-[11px] font-medium uppercase tracking-wide text-white/70">
|
|
52
|
+
{{ t('header.profile.tariff') }}
|
|
53
|
+
</p>
|
|
54
|
+
<div class="mt-0.5 flex items-center justify-between gap-2">
|
|
55
|
+
<p class="truncate text-lg font-bold leading-tight">
|
|
56
|
+
{{ rate }}
|
|
57
|
+
</p>
|
|
58
|
+
<span class="inline-flex shrink-0 items-center gap-1.5 rounded-full px-2 py-0.5 text-[11px] font-medium text-white ring-1 ring-inset ring-white/20">
|
|
59
|
+
<span class="relative flex size-1.5 items-center justify-center">
|
|
60
|
+
<span class="absolute inline-flex size-full animate-ping rounded-full bg-green-400/80" />
|
|
61
|
+
<span class="relative inline-flex size-1.5 rounded-full bg-green-400" />
|
|
62
|
+
</span>
|
|
63
|
+
{{ t('header.profile.connected') }}
|
|
64
|
+
</span>
|
|
90
65
|
</div>
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
66
|
+
|
|
67
|
+
<!-- Email (mobile only — desktop shows it in the header trigger) -->
|
|
68
|
+
<p
|
|
69
|
+
v-if="email"
|
|
70
|
+
class="mt-1 truncate text-xs text-white/75 lg:hidden"
|
|
71
|
+
data-test-id="profile-menu-email"
|
|
95
72
|
>
|
|
96
|
-
{{
|
|
97
|
-
</
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
73
|
+
{{ email }}
|
|
74
|
+
</p>
|
|
75
|
+
|
|
76
|
+
<div class="my-2 h-px bg-white/15" />
|
|
77
|
+
|
|
78
|
+
<!-- Balance -->
|
|
79
|
+
<div class="flex items-center justify-between gap-2">
|
|
80
|
+
<span class="text-xs text-white/80">{{ t('header.profile.currentBalance') }}</span>
|
|
81
|
+
<span class="text-base font-bold tabular-nums">{{ formattedBalance }} ₸</span>
|
|
102
82
|
</div>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
/>
|
|
119
|
-
|
|
83
|
+
|
|
84
|
+
<!-- Usage stats (mobile only — desktop shows them in the header bar) -->
|
|
85
|
+
<div class="mt-2 grid grid-cols-2 gap-2 lg:hidden">
|
|
86
|
+
<div class="flex items-center gap-2 rounded-lg px-2 py-1.5 ring-1 ring-inset ring-white/15">
|
|
87
|
+
<gauge class="size-4 shrink-0 text-white/80" />
|
|
88
|
+
<div class="min-w-0">
|
|
89
|
+
<p class="truncate text-[10px] uppercase leading-none text-white/70">
|
|
90
|
+
{{ t('header.profile.requests') }}
|
|
91
|
+
</p>
|
|
92
|
+
<p class="mt-1 text-sm font-bold tabular-nums leading-none">
|
|
93
|
+
{{ limitRemaining }}
|
|
94
|
+
</p>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
<div class="flex items-center gap-2 rounded-lg px-2 py-1.5 ring-1 ring-inset ring-white/15">
|
|
98
|
+
<calendar class="size-4 shrink-0 text-white/80" />
|
|
99
|
+
<div class="min-w-0">
|
|
100
|
+
<p class="truncate text-[10px] uppercase leading-none text-white/70">
|
|
101
|
+
{{ t('header.profile.daysLeft') }}
|
|
102
|
+
</p>
|
|
103
|
+
<p class="mt-1 text-sm font-bold tabular-nums leading-none">
|
|
104
|
+
{{ daysRemaining }}
|
|
105
|
+
</p>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
120
108
|
</div>
|
|
109
|
+
|
|
110
|
+
<!-- Top up -->
|
|
111
|
+
<button
|
|
112
|
+
type="button"
|
|
113
|
+
class="mt-2.5 inline-flex h-8 w-full cursor-pointer items-center justify-center gap-1.5 rounded-full bg-white px-3 text-sm font-semibold text-blue-700 shadow-sm transition-all duration-150 hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/70 focus-visible:ring-offset-2 focus-visible:ring-offset-blue-600 active:scale-[0.98]"
|
|
114
|
+
@click="onReplenish"
|
|
115
|
+
>
|
|
116
|
+
<a-icon-plus-circle class="size-4" />
|
|
117
|
+
<span class="bg-gradient-to-r from-blue-700 to-blue-500 bg-clip-text text-transparent">
|
|
118
|
+
{{ t('header.profile.addBalance') }}
|
|
119
|
+
</span>
|
|
120
|
+
</button>
|
|
121
121
|
</div>
|
|
122
122
|
</div>
|
|
123
123
|
</div>
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
{{
|
|
145
|
-
</
|
|
146
|
-
</
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
class="h-[24px] w-[24px]"
|
|
158
|
-
/>
|
|
159
|
-
<span class="dark:text-[#E3E5E8] text-[#2C3E50]">{{ item.title }}</span>
|
|
160
|
-
</nuxt-link-locale>
|
|
161
|
-
</div>
|
|
162
|
-
<div class="mt-2">
|
|
163
|
-
<a-change-version
|
|
164
|
-
v-if="oldVersion"
|
|
165
|
-
:url="oldVersion"
|
|
166
|
-
/>
|
|
167
|
-
</div>
|
|
124
|
+
|
|
125
|
+
<!-- Menu links -->
|
|
126
|
+
<nav class="flex flex-col px-2 pb-2">
|
|
127
|
+
<nuxt-link-locale
|
|
128
|
+
v-for="item in items"
|
|
129
|
+
:key="item.title"
|
|
130
|
+
class="group flex items-center gap-3 rounded-lg px-2.5 py-2 text-sm transition-colors hover:bg-gray-50 dark:hover:bg-gray-800/60"
|
|
131
|
+
:to="item.to"
|
|
132
|
+
:data-test-id="item?.dataTestId"
|
|
133
|
+
target="_blank"
|
|
134
|
+
>
|
|
135
|
+
<!-- <span-->
|
|
136
|
+
<!-- class="flex size-8 shrink-0 items-center justify-center rounded-lg border border-blue-100 bg-blue-50 text-blue-700 dark:border-blue-900/40 dark:bg-blue-900/30 dark:text-blue-400"-->
|
|
137
|
+
<!-- >-->
|
|
138
|
+
<!-- <component-->
|
|
139
|
+
<!-- :is="item.icon"-->
|
|
140
|
+
<!-- class="size-4"-->
|
|
141
|
+
<!-- />-->
|
|
142
|
+
<!-- </span>-->
|
|
143
|
+
<span class="truncate text-deepblue-900 group-hover:text-blue-700 dark:text-gray-200 dark:group-hover:text-blue-400">
|
|
144
|
+
{{ item.title }}
|
|
145
|
+
</span>
|
|
146
|
+
</nuxt-link-locale>
|
|
147
|
+
</nav>
|
|
148
|
+
|
|
149
|
+
<!-- Footer: old version, theme (mobile), logout -->
|
|
150
|
+
<div class="border-t border-gray-100 p-2 dark:border-gray-800">
|
|
151
|
+
<a-change-version
|
|
152
|
+
v-if="oldVersion"
|
|
153
|
+
:url="oldVersion"
|
|
154
|
+
class="mb-2"
|
|
155
|
+
/>
|
|
156
|
+
|
|
168
157
|
<div
|
|
169
158
|
v-if="!isLargeScreen"
|
|
170
|
-
class="
|
|
159
|
+
class="flex items-center justify-between rounded-lg px-2.5 py-2 text-sm text-deepblue-900 dark:text-gray-200"
|
|
171
160
|
>
|
|
172
|
-
<span>
|
|
173
|
-
{{ t('header.profile.colorScheme') }}
|
|
174
|
-
</span>
|
|
161
|
+
<span>{{ t('header.profile.colorScheme') }}</span>
|
|
175
162
|
<a-color-mode />
|
|
176
163
|
</div>
|
|
177
164
|
|
|
178
|
-
<
|
|
179
|
-
|
|
165
|
+
<button
|
|
166
|
+
type="button"
|
|
167
|
+
class="flex w-full cursor-pointer items-center gap-3 rounded-lg px-2.5 py-2 text-sm font-medium text-red-600 transition-colors hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-900/20"
|
|
180
168
|
data-test-id="logout-button"
|
|
181
169
|
@click="$emit('logout')"
|
|
182
170
|
>
|
|
183
|
-
<icon-logout class="
|
|
184
|
-
<span>
|
|
185
|
-
|
|
186
|
-
</span>
|
|
187
|
-
</div>
|
|
171
|
+
<icon-logout class="size-4 shrink-0" />
|
|
172
|
+
<span>{{ t('header.profile.logout') }}</span>
|
|
173
|
+
</button>
|
|
188
174
|
</div>
|
|
189
175
|
</div>
|
|
190
176
|
</template>
|
|
191
|
-
<style scoped>
|
|
192
|
-
.gradient-bg {
|
|
193
|
-
background: linear-gradient(236.46deg, #479fff -2.39%, #0070eb 79.1%);
|
|
194
|
-
}
|
|
195
|
-
</style>
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useCurrentModule } from '#adata-ui/composables/projectState'
|
|
3
|
+
|
|
4
|
+
defineOptions({ name: 'SystemNotification' })
|
|
5
|
+
|
|
6
|
+
interface SystemMessageDetail {
|
|
7
|
+
message: string
|
|
8
|
+
message_en: string
|
|
9
|
+
message_kz: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { locale } = useI18n()
|
|
13
|
+
const { myLayer } = useAppConfig()
|
|
14
|
+
const env = myLayer.mode
|
|
15
|
+
|
|
16
|
+
const currentModule = useCurrentModule()
|
|
17
|
+
const message = useCookie('message')
|
|
18
|
+
|
|
19
|
+
const systemMessage = ref<string | null>(null)
|
|
20
|
+
const isOpen = ref(false)
|
|
21
|
+
|
|
22
|
+
// API expects the legacy "counterparty" code instead of "pk".
|
|
23
|
+
const moduleName = computed(() => (currentModule.value === 'pk' ? 'counterparty' : currentModule.value))
|
|
24
|
+
|
|
25
|
+
function localizedMessage(detail: SystemMessageDetail): string {
|
|
26
|
+
switch (locale.value) {
|
|
27
|
+
case 'en':
|
|
28
|
+
return detail.message_en
|
|
29
|
+
case 'kk':
|
|
30
|
+
return detail.message_kz
|
|
31
|
+
default:
|
|
32
|
+
return detail.message
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function fetchNotification() {
|
|
37
|
+
// The cookie is set once the user dismisses the banner — skip the request afterwards.
|
|
38
|
+
if (message.value !== undefined) return
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const res = await $fetch<{ data: { details?: SystemMessageDetail[] } }>(
|
|
42
|
+
`https://users.${env}.kz/api/v1/system-messages/active-list/`,
|
|
43
|
+
{ query: { module_name: moduleName.value } },
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
const detail = res.data?.details?.[0]
|
|
47
|
+
if (detail) {
|
|
48
|
+
systemMessage.value = localizedMessage(detail)
|
|
49
|
+
isOpen.value = true
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
console.error(e instanceof Error ? e.message : e)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function close() {
|
|
58
|
+
message.value = false
|
|
59
|
+
isOpen.value = false
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
onMounted(fetchNotification)
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<template>
|
|
66
|
+
<client-only>
|
|
67
|
+
<transition name="system-notification">
|
|
68
|
+
<div
|
|
69
|
+
v-if="isOpen && systemMessage"
|
|
70
|
+
class="bg-[#FFF5E6] px-2 py-3 dark:bg-[#161617] md:px-0"
|
|
71
|
+
>
|
|
72
|
+
<div class="a-container flex items-center justify-between gap-4">
|
|
73
|
+
<div class="flex items-center gap-2">
|
|
74
|
+
<a-icon-info-circle
|
|
75
|
+
class="max-h-[16px] w-full max-w-[16px] shrink-0 stroke-orange-500"
|
|
76
|
+
/>
|
|
77
|
+
<span class="text-sm font-semibold text-orange-500">{{ systemMessage }}</span>
|
|
78
|
+
</div>
|
|
79
|
+
<a-icon-x-mark
|
|
80
|
+
class="max-h-[16px] w-full max-w-[16px] shrink-0 cursor-pointer stroke-orange-500"
|
|
81
|
+
@click="close"
|
|
82
|
+
/>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
</transition>
|
|
86
|
+
</client-only>
|
|
87
|
+
</template>
|
|
88
|
+
|
|
89
|
+
<style scoped>
|
|
90
|
+
.system-notification-enter-active,
|
|
91
|
+
.system-notification-leave-active {
|
|
92
|
+
transition:
|
|
93
|
+
opacity 200ms ease,
|
|
94
|
+
transform 200ms ease;
|
|
95
|
+
overflow: hidden;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.system-notification-enter-from,
|
|
99
|
+
.system-notification-leave-to {
|
|
100
|
+
opacity: 0;
|
|
101
|
+
transform: translateY(-100%);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@media (prefers-reduced-motion: reduce) {
|
|
105
|
+
.system-notification-enter-active,
|
|
106
|
+
.system-notification-leave-active {
|
|
107
|
+
transition: none;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
</style>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import
|
|
3
|
-
import IconInvoice from '#adata-ui/icons/invoice.vue'
|
|
4
|
-
import ContentNavigationModal from '#adata-ui/components/modals/ContentNavigationModal.vue'
|
|
2
|
+
import type { ProjectKeys } from '#adata-ui/components/navigation/header/types'
|
|
5
3
|
import ContactsMobileModel from '#adata-ui/components/modals/ContactsMobileModel.vue'
|
|
4
|
+
import ContentNavigationModal from '#adata-ui/components/modals/ContentNavigationModal.vue'
|
|
6
5
|
import ProfileMenu from '#adata-ui/components/navigation/header/ProfileMenu.vue'
|
|
7
|
-
import
|
|
6
|
+
import AModal from '#adata-ui/components/overlays/modal/AModal.vue'
|
|
8
7
|
import { useCurrentModule } from '#adata-ui/composables/projectState'
|
|
9
|
-
import AModal from "#adata-ui/components/overlays/modal/AModal.vue";
|
|
10
8
|
import { useUrls } from '#adata-ui/composables/useUrls'
|
|
9
|
+
import IconInvoice from '#adata-ui/icons/invoice.vue'
|
|
10
|
+
import IconMenu from '#adata-ui/icons/menu-filled.vue'
|
|
11
11
|
|
|
12
12
|
interface Props {
|
|
13
13
|
replenish?: string
|
|
@@ -28,7 +28,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
28
28
|
balance: 0,
|
|
29
29
|
rate: 'Базовый',
|
|
30
30
|
showLogIn: true,
|
|
31
|
-
module: 'pk'
|
|
31
|
+
module: 'pk',
|
|
32
32
|
})
|
|
33
33
|
const emit = defineEmits(['logout'])
|
|
34
34
|
useCurrentModule().value = props.module
|
|
@@ -42,13 +42,13 @@ const items = [
|
|
|
42
42
|
{
|
|
43
43
|
label: 'modals.mobile_navigation.type_tariff',
|
|
44
44
|
icon: IconInvoice,
|
|
45
|
-
value: 'tariff'
|
|
45
|
+
value: 'tariff',
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
label: 'modals.mobile_navigation.type_main',
|
|
49
49
|
icon: IconMenu,
|
|
50
|
-
value: 'main'
|
|
51
|
-
}
|
|
50
|
+
value: 'main',
|
|
51
|
+
},
|
|
52
52
|
]
|
|
53
53
|
function onLogout() {
|
|
54
54
|
emit('logout')
|
|
@@ -57,11 +57,14 @@ function onLogout() {
|
|
|
57
57
|
watch(activeModule, (e) => {
|
|
58
58
|
if (e === 'main') {
|
|
59
59
|
isMain.value = true
|
|
60
|
-
}
|
|
60
|
+
}
|
|
61
|
+
else if (e === 'contacts') {
|
|
61
62
|
isContacts.value = true
|
|
62
|
-
}
|
|
63
|
+
}
|
|
64
|
+
else if (e === 'profile') {
|
|
63
65
|
isProfile.value = true
|
|
64
|
-
}
|
|
66
|
+
}
|
|
67
|
+
else if (e === 'tariff') {
|
|
65
68
|
navigateTo(`${landing}/tariffs`, { external: true })
|
|
66
69
|
}
|
|
67
70
|
activeModule.value = ''
|
|
@@ -72,9 +75,14 @@ watch(activeModule, (e) => {
|
|
|
72
75
|
<div>
|
|
73
76
|
<content-navigation-modal v-model="isMain" @push-main="isMain = false" />
|
|
74
77
|
<contacts-mobile-model v-model="isContacts" @push-main="isContacts = false" />
|
|
75
|
-
<a-modal
|
|
78
|
+
<a-modal
|
|
79
|
+
v-model="isProfile"
|
|
80
|
+
@logout="isProfile = false"
|
|
81
|
+
@push-main="isProfile = false"
|
|
82
|
+
>
|
|
76
83
|
<div class="-mx-4">
|
|
77
84
|
<profile-menu
|
|
85
|
+
:email="email"
|
|
78
86
|
:balance="balance"
|
|
79
87
|
:days-remaining="daysRemaining"
|
|
80
88
|
:limit-remaining="limitRemaining"
|
|
@@ -87,15 +95,15 @@ watch(activeModule, (e) => {
|
|
|
87
95
|
</a-modal>
|
|
88
96
|
<div ref="bottom" class="sticky bottom-0 z-[10000] lg:hidden">
|
|
89
97
|
<a-bottom-navigation
|
|
98
|
+
v-model="activeModule"
|
|
90
99
|
:is-authenticated="isAuthenticated"
|
|
91
100
|
:email="email"
|
|
92
101
|
:days-remaining="daysRemaining"
|
|
93
102
|
:limit-remaining="limitRemaining"
|
|
94
103
|
:rate="rate"
|
|
95
104
|
:balance="balance"
|
|
96
|
-
@logout="onLogout"
|
|
97
|
-
v-model="activeModule"
|
|
98
105
|
:items="items"
|
|
106
|
+
@logout="onLogout"
|
|
99
107
|
/>
|
|
100
108
|
</div>
|
|
101
109
|
</div>
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
activeTab === option.key ? selectedClasses() : defaultClasses(!!option.disabled),
|
|
18
18
|
sizeOptions[size]
|
|
19
19
|
]"
|
|
20
|
-
:data-test-id="option
|
|
20
|
+
:data-test-id="getTestId(option)"
|
|
21
21
|
@click="onChanged(option, $event)"
|
|
22
22
|
>
|
|
23
23
|
<slot name="option" :option="option">
|
|
@@ -62,6 +62,7 @@ interface Props {
|
|
|
62
62
|
wrapper?: 'column' | 'row'
|
|
63
63
|
countView?: 'badge' | 'brackets'
|
|
64
64
|
disabled?: boolean
|
|
65
|
+
mobileTestId?: boolean
|
|
65
66
|
}
|
|
66
67
|
|
|
67
68
|
const props = withDefaults(defineProps<Props>(), {
|
|
@@ -71,7 +72,8 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
71
72
|
badgeSize: 'lg',
|
|
72
73
|
block: false,
|
|
73
74
|
wrapper: 'row',
|
|
74
|
-
countView: 'badge'
|
|
75
|
+
countView: 'badge',
|
|
76
|
+
mobileTestId: false,
|
|
75
77
|
})
|
|
76
78
|
const tabs = ref<HTMLDivElement | null>(null)
|
|
77
79
|
const activeTab = defineModel<any>({ default: 1 })
|
|
@@ -148,6 +150,9 @@ const onChanged = (option: Tab, event) => {
|
|
|
148
150
|
})
|
|
149
151
|
}
|
|
150
152
|
|
|
153
|
+
const getTestId = (option: Tab) =>
|
|
154
|
+
option?.dataTestId ? `${option.dataTestId}${props.mobileTestId ? '-mobile' : ''}` : undefined
|
|
155
|
+
|
|
151
156
|
onMounted(() => {
|
|
152
157
|
const isDesktop = window.matchMedia('(min-width: 1024px)').matches
|
|
153
158
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
# tooltip, popover, slide over, modal, context menu
|
|
1
|
+
# tooltip, popover, slide over, modal, context menu
|