adata-ui 2.1.40-beta.1 → 2.1.40-beta.11

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 (56) hide show
  1. package/.claude/settings.local.json +19 -0
  2. package/components/elements/a-select-row/ASelectRowV2.vue +214 -0
  3. package/components/elements/button/AButtonV2.vue +112 -0
  4. package/components/elements/leave-note/ALeaveNote.vue +38 -17
  5. package/components/elements/segmented/ASegmentedV2.vue +58 -0
  6. package/components/elements/select/ASelectV2.vue +589 -0
  7. package/components/elements/show-more/AShowMoreV2.vue +26 -0
  8. package/components/elements/star-rating/AStarRating.vue +12 -4
  9. package/components/elements/status-badge-v2/StatusBadgeV2.vue +78 -0
  10. package/components/features/payment/process/PaymentKaspiQrSidePanel.vue +43 -27
  11. package/components/features/payment/process/PaymentKaspiRedirectSidePanel.vue +34 -23
  12. package/components/features/payment/process/PaymentMethodSidePanel.vue +61 -49
  13. package/components/features/payment/process/PaymentProcess.vue +6 -6
  14. package/components/features/payment/process/PaymentTopUpSidePanel.vue +44 -63
  15. package/components/forms/checkbox/ACheckboxV2.vue +229 -0
  16. package/components/forms/feedback-form/FeedbackForm.vue +8 -8
  17. package/components/forms/input/AInputV2.vue +542 -0
  18. package/components/forms/input/textarea/ATextareaV2.vue +248 -0
  19. package/components/forms/toggle/AToggleV2.vue +71 -0
  20. package/components/modals/AnotherDeviceModal.vue +22 -18
  21. package/components/modals/ApplicationAcceptedModal.vue +12 -15
  22. package/components/modals/ConnectingTariffModal.vue +13 -20
  23. package/components/modals/ContentNavigationModal.vue +77 -333
  24. package/components/modals/Insufficient-funds-modal.vue +18 -33
  25. package/components/modals/LimitReachedModal.vue +4 -3
  26. package/components/modals/NoAccessModal.vue +9 -11
  27. package/components/modals/PaymentMethodModal.vue +1 -1
  28. package/components/modals/ReportBugConfirmModal.vue +12 -10
  29. package/components/modals/ReportBugModal.vue +42 -36
  30. package/components/modals/Resend.vue +9 -10
  31. package/components/modals/SubmitApplicationModal.vue +27 -24
  32. package/components/modals/id/IdConfirmAccountOtpModal.vue +4 -9
  33. package/components/modals/id/IdLoginModal.vue +3 -8
  34. package/components/modals/id/IdModals.vue +23 -10
  35. package/components/modals/id/IdTwoFactorModal.vue +3 -8
  36. package/components/navigation/bottom-navigation/ABottomNavigation.vue +1 -1
  37. package/components/navigation/header/AHeader.vue +15 -19
  38. package/components/navigation/header/HeaderLink.vue +15 -21
  39. package/components/navigation/header/NavList.vue +8 -32
  40. package/components/navigation/header/ProductMenu.vue +52 -50
  41. package/components/navigation/pill-tabs/APillTabsV2.vue +134 -0
  42. package/components/overlays/modal/AModalV2.vue +391 -0
  43. package/composables/useAccessTokenCookie.ts +25 -0
  44. package/composables/useChipOverflow.ts +92 -0
  45. package/composables/useHeaderNavigationLinks.ts +53 -23
  46. package/icons/arrow/arrow-right.vue +14 -0
  47. package/icons/briefcase.vue +14 -0
  48. package/icons/car-side.vue +16 -0
  49. package/icons/cart.vue +15 -0
  50. package/icons/download-rounded.vue +15 -0
  51. package/icons/shield-verified.vue +14 -0
  52. package/lang/en.ts +35 -4
  53. package/lang/kk.ts +36 -5
  54. package/lang/ru.ts +37 -6
  55. package/package.json +1 -1
  56. package/shared/constans/pages.ts +8 -2
@@ -0,0 +1,391 @@
1
+ <script setup lang="ts">
2
+ import { onKeyStroke, useScrollLock, useWindowSize } from '@vueuse/core'
3
+
4
+ type ModalSize = 'sm' | 'md' | 'lg' | 'xl' | 'container' | 'fullscreen'
5
+
6
+ const props = withDefaults(defineProps<{
7
+ title?: string
8
+ size?: ModalSize
9
+ width?: string
10
+ closeOnOverlay?: boolean
11
+ closeOnEsc?: boolean
12
+ lockScroll?: boolean
13
+ persistent?: boolean
14
+ transition?: boolean
15
+ contentClass?: string
16
+ hideHeader?: boolean
17
+ hideClose?: boolean
18
+ blur?: boolean | 'sm' | 'md' | 'lg' | 'xl'
19
+ mobileSheet?: boolean
20
+ swipeToClose?: boolean
21
+ swipeThreshold?: number
22
+ showDragHandle?: boolean
23
+ }>(), {
24
+ size: 'md',
25
+ closeOnOverlay: true,
26
+ closeOnEsc: true,
27
+ lockScroll: true,
28
+ persistent: false,
29
+ transition: true,
30
+ hideHeader: false,
31
+ hideClose: false,
32
+ blur: false,
33
+ mobileSheet: true,
34
+ swipeToClose: true,
35
+ swipeThreshold: 65,
36
+ showDragHandle: true,
37
+ })
38
+
39
+ const emit = defineEmits<{
40
+ (e: 'close'): void
41
+ (e: 'open'): void
42
+ }>()
43
+
44
+ const open = defineModel<boolean>({ required: true })
45
+
46
+ const contentRef = ref<HTMLElement | null>(null)
47
+ const overlayRef = ref<HTMLElement | null>(null)
48
+ const swipeClosing = ref(false)
49
+ const bodyScrollLocked = useScrollLock(import.meta.client ? document.body : null)
50
+ const { width: windowWidth } = useWindowSize()
51
+
52
+ const isMobile = computed(() => windowWidth.value < 1025)
53
+ const isSheet = computed(() => isMobile.value && props.mobileSheet)
54
+
55
+ const sizeStyle = computed(() => {
56
+ if (isSheet.value) return { width: '100%' }
57
+ if (props.width) return { width: props.width }
58
+
59
+ switch (props.size) {
60
+ case 'sm': return { width: '380px' }
61
+ case 'md': return { width: '520px' }
62
+ case 'lg': return { width: '720px' }
63
+ case 'xl': return { width: '1100px' }
64
+ case 'container': return {}
65
+ case 'fullscreen': return { width: '100vw', height: '100vh' }
66
+ default: return { width: '520px' }
67
+ }
68
+ })
69
+
70
+ const blurClass = computed(() => {
71
+ if (!props.blur) return ''
72
+
73
+ switch (props.blur) {
74
+ case 'sm': return 'backdrop-blur-sm'
75
+ case 'md': return 'backdrop-blur-md'
76
+ case 'lg': return 'backdrop-blur-lg'
77
+ case 'xl': return 'backdrop-blur-xl'
78
+ default: return 'backdrop-blur'
79
+ }
80
+ })
81
+
82
+ const overlayClass = computed(() => {
83
+ const base = ['modal-v2-overlay fixed inset-0 z-[10000] flex bg-black/40 dark:bg-black/60']
84
+
85
+ if (isSheet.value) {
86
+ base.push('items-end justify-stretch')
87
+ }
88
+ else {
89
+ base.push(props.size === 'container' ? 'items-center justify-center' : 'items-center justify-center p-4')
90
+ }
91
+
92
+ if (blurClass.value) base.push(blurClass.value)
93
+
94
+ return base.join(' ')
95
+ })
96
+
97
+ const contentBaseClass = computed(() => {
98
+ const base = ['modal-v2-content flex flex-col overflow-hidden border bg-white shadow-2xl dark:bg-gray-900']
99
+
100
+ if (isSheet.value) {
101
+ base.push('w-full max-w-none max-h-[100dvh] rounded-t-2xl rounded-b-none border-x-0 border-b-0 border-t border-gray-200 dark:border-gray-800')
102
+ }
103
+ else {
104
+ const radius = props.size === 'fullscreen' ? 'rounded-none' : 'rounded-2xl'
105
+ const widthCls = props.size === 'container'
106
+ ? ' w-full max-w-screen-sm md:max-w-screen-md lg:max-w-screen-lg xl:max-w-screen-xl 2xl:max-w-screen-2xl'
107
+ : ''
108
+ base.push(`max-h-[calc(100vh-2rem)] border-gray-200 dark:border-gray-800 ${radius}${widthCls}`)
109
+ }
110
+
111
+ return base.join(' ')
112
+ })
113
+
114
+ const overlayTransitionName = computed(() => {
115
+ if (swipeClosing.value) return ''
116
+ return props.transition ? 'modal-v2-overlay' : ''
117
+ })
118
+ const contentTransitionName = computed(() => {
119
+ if (swipeClosing.value || !props.transition) return ''
120
+ return isSheet.value ? 'modal-v2-sheet' : 'modal-v2-content'
121
+ })
122
+
123
+ function closeIfAllowed() {
124
+ if (props.persistent) return
125
+ open.value = false
126
+ }
127
+
128
+ function onOverlayClick(event: MouseEvent) {
129
+ if (!props.closeOnOverlay || props.persistent) return
130
+ if (event.target === event.currentTarget) {
131
+ open.value = false
132
+ }
133
+ }
134
+
135
+ onKeyStroke('Escape', () => {
136
+ if (!open.value) return
137
+ if (!props.closeOnEsc || props.persistent) return
138
+ open.value = false
139
+ })
140
+
141
+ function setScrollbarCompensation(active: boolean) {
142
+ if (!import.meta.client) return
143
+
144
+ if (active) {
145
+ const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth
146
+ document.body.style.paddingRight = scrollbarWidth > 0 ? `${scrollbarWidth}px` : ''
147
+ }
148
+ else {
149
+ document.body.style.paddingRight = ''
150
+ }
151
+ }
152
+
153
+ watch(open, (value) => {
154
+ if (props.lockScroll) {
155
+ if (value) setScrollbarCompensation(true)
156
+ bodyScrollLocked.value = value
157
+ if (!value) setScrollbarCompensation(false)
158
+ }
159
+
160
+ if (value) emit('open')
161
+ else emit('close')
162
+ })
163
+
164
+ onBeforeUnmount(() => {
165
+ if (bodyScrollLocked.value) {
166
+ bodyScrollLocked.value = false
167
+ }
168
+ setScrollbarCompensation(false)
169
+ })
170
+
171
+ const dragging = ref(false)
172
+ const dragStartY = ref(0)
173
+ const dragDelta = ref(0)
174
+
175
+ function canSwipe() {
176
+ return isSheet.value && props.swipeToClose && !props.persistent
177
+ }
178
+
179
+ function setTransform(value: string) {
180
+ if (contentRef.value) {
181
+ contentRef.value.style.transform = value
182
+ }
183
+ }
184
+
185
+ function onTouchStart(event: TouchEvent) {
186
+ if (!canSwipe()) return
187
+ dragging.value = true
188
+ dragStartY.value = event.touches[0].clientY
189
+ dragDelta.value = 0
190
+
191
+ if (contentRef.value) {
192
+ contentRef.value.style.transition = 'none'
193
+ }
194
+ }
195
+
196
+ function onTouchMove(event: TouchEvent) {
197
+ if (!dragging.value || !canSwipe()) return
198
+
199
+ const delta = event.touches[0].clientY - dragStartY.value
200
+ if (delta < 0) {
201
+ dragDelta.value = 0
202
+ setTransform('')
203
+ return
204
+ }
205
+
206
+ dragDelta.value = delta
207
+ setTransform(`translateY(${delta}px)`)
208
+ }
209
+
210
+ function prefersReducedMotion() {
211
+ return import.meta.client && window.matchMedia('(prefers-reduced-motion: reduce)').matches
212
+ }
213
+
214
+ function animateClose() {
215
+ const content = contentRef.value
216
+
217
+ if (!content || prefersReducedMotion()) {
218
+ open.value = false
219
+ return
220
+ }
221
+
222
+ swipeClosing.value = true
223
+
224
+ let done = false
225
+ const finish = () => {
226
+ if (done) return
227
+ done = true
228
+ content.removeEventListener('transitionend', onTransitionEnd)
229
+ open.value = false
230
+ swipeClosing.value = false
231
+ }
232
+
233
+ function onTransitionEnd(event: TransitionEvent) {
234
+ if (event.target === content && event.propertyName === 'transform') {
235
+ finish()
236
+ }
237
+ }
238
+
239
+ content.addEventListener('transitionend', onTransitionEnd)
240
+ setTimeout(finish, 320)
241
+
242
+ requestAnimationFrame(() => {
243
+ content.style.transition = 'transform 260ms cubic-bezier(0.22, 1, 0.36, 1)'
244
+ content.style.transform = 'translateY(100%)'
245
+
246
+ if (overlayRef.value) {
247
+ overlayRef.value.style.transition = 'opacity 260ms ease'
248
+ overlayRef.value.style.opacity = '0'
249
+ }
250
+ })
251
+ }
252
+
253
+ function onTouchEnd() {
254
+ if (!dragging.value) return
255
+ dragging.value = false
256
+
257
+ const shouldClose = dragDelta.value > props.swipeThreshold && canSwipe()
258
+
259
+ if (shouldClose) {
260
+ animateClose()
261
+ }
262
+ else {
263
+ if (contentRef.value) {
264
+ contentRef.value.style.transition = 'transform 220ms cubic-bezier(0.22, 1, 0.36, 1)'
265
+ contentRef.value.style.transform = ''
266
+ }
267
+ }
268
+
269
+ dragDelta.value = 0
270
+ }
271
+ </script>
272
+
273
+ <template>
274
+ <client-only>
275
+ <teleport to="body">
276
+ <transition :name="overlayTransitionName">
277
+ <div
278
+ v-if="open"
279
+ ref="overlayRef"
280
+ :class="overlayClass"
281
+ @mousedown="onOverlayClick"
282
+ >
283
+ <transition :name="contentTransitionName" appear>
284
+ <div
285
+ v-if="open"
286
+ ref="contentRef"
287
+ :class="contentBaseClass"
288
+ :style="sizeStyle"
289
+ @mousedown.stop
290
+ >
291
+ <div
292
+ v-if="isSheet && showDragHandle"
293
+ class="flex shrink-0 cursor-grab touch-none justify-center py-2"
294
+ @touchstart.passive="onTouchStart"
295
+ @touchmove="onTouchMove"
296
+ @touchend="onTouchEnd"
297
+ @touchcancel="onTouchEnd"
298
+ >
299
+ <div class="h-1 w-10 rounded-full bg-gray-300 dark:bg-gray-600" />
300
+ </div>
301
+
302
+ <header
303
+ v-if="!hideHeader"
304
+ class="flex shrink-0 items-center justify-between gap-3 border-b border-gray-200 px-5 py-4 dark:border-gray-800"
305
+ @touchstart.passive="onTouchStart"
306
+ @touchmove="onTouchMove"
307
+ @touchend="onTouchEnd"
308
+ @touchcancel="onTouchEnd"
309
+ >
310
+ <slot name="header">
311
+ <h2 v-if="title" class="text-base font-semibold text-gray-900 dark:text-gray-100">
312
+ {{ title }}
313
+ </h2>
314
+ </slot>
315
+ <button
316
+ v-if="!hideClose"
317
+ type="button"
318
+ class="ml-auto rounded-md p-1 transition hover:bg-gray-100 dark:hover:bg-gray-800 dark:hover:text-gray-200"
319
+ @click="closeIfAllowed"
320
+ >
321
+ <a-icon-x-mark class="size-4" />
322
+ </button>
323
+ </header>
324
+
325
+ <div class="min-h-0 flex-1 overflow-auto" :class="contentClass">
326
+ <slot :close="closeIfAllowed" />
327
+ </div>
328
+
329
+ <footer
330
+ v-if="$slots.footer"
331
+ class="shrink-0 border-t border-gray-200 px-5 py-4 dark:border-gray-800"
332
+ >
333
+ <slot name="footer" :close="closeIfAllowed" />
334
+ </footer>
335
+ </div>
336
+ </transition>
337
+ </div>
338
+ </transition>
339
+ </teleport>
340
+ </client-only>
341
+ </template>
342
+
343
+ <style scoped lang="scss">
344
+ .modal-v2-overlay-enter-active {
345
+ transition: opacity 200ms ease-out;
346
+ }
347
+
348
+ .modal-v2-overlay-leave-active {
349
+ transition: opacity 150ms ease-in;
350
+ }
351
+
352
+ .modal-v2-overlay-enter-from,
353
+ .modal-v2-overlay-leave-to {
354
+ opacity: 0;
355
+ }
356
+
357
+ .modal-v2-content-enter-active {
358
+ transition: transform 220ms cubic-bezier(0.22, 1, 0.36, 1), opacity 220ms ease-out;
359
+ }
360
+
361
+ .modal-v2-content-leave-active {
362
+ transition: transform 150ms ease-in, opacity 150ms ease-in;
363
+ }
364
+
365
+ .modal-v2-content-enter-from,
366
+ .modal-v2-content-leave-to {
367
+ opacity: 0;
368
+ transform: translateY(8px) scale(0.98);
369
+ }
370
+
371
+ .modal-v2-sheet-enter-active,
372
+ .modal-v2-sheet-leave-active {
373
+ transition: transform 280ms cubic-bezier(0.22, 1, 0.36, 1);
374
+ }
375
+
376
+ .modal-v2-sheet-enter-from,
377
+ .modal-v2-sheet-leave-to {
378
+ transform: translateY(100%);
379
+ }
380
+
381
+ @media (prefers-reduced-motion: reduce) {
382
+ .modal-v2-overlay-enter-active,
383
+ .modal-v2-overlay-leave-active,
384
+ .modal-v2-content-enter-active,
385
+ .modal-v2-content-leave-active,
386
+ .modal-v2-sheet-enter-active,
387
+ .modal-v2-sheet-leave-active {
388
+ transition: none;
389
+ }
390
+ }
391
+ </style>
@@ -0,0 +1,25 @@
1
+ import { useUrls } from '#adata-ui/composables/useUrls'
2
+
3
+ /**
4
+ * Единая точка записи куки accessToken (логин, 2FA, OTP, обмен по auth-сессии).
5
+ * Домен должен совпадать с доменом удаления в resetTokens (adata-common-auth),
6
+ * иначе кука не находится на следующей загрузке и логин-флоу зацикливается на reload.
7
+ */
8
+ export async function writeAccessTokenCookie(accessToken: string, expireIn?: number): Promise<boolean> {
9
+ const { mode } = useUrls()
10
+ const sharedDomain = `${mode}.kz`
11
+ const onSharedDomain = location.hostname === sharedDomain || location.hostname.endsWith(`.${sharedDomain}`)
12
+ const maxAge = Number(expireIn) > 0 ? Number(expireIn) : undefined
13
+
14
+ useCookie('accessToken', {
15
+ maxAge,
16
+ // на localhost/превью-хостах атрибут domain невалиден — пишем host-only куку
17
+ domain: onSharedDomain ? `.${sharedDomain}` : undefined,
18
+ path: '/',
19
+ secure: location.protocol === 'https:',
20
+ }).value = accessToken
21
+
22
+ // useCookie пишет document.cookie на следующем flush, не синхронно
23
+ await nextTick()
24
+ return document.cookie.split('; ').some(part => part.startsWith('accessToken='))
25
+ }
@@ -0,0 +1,92 @@
1
+ import type { ComputedRef, Ref } from 'vue'
2
+
3
+ interface UseChipOverflowOptions {
4
+ container: Ref<HTMLElement | null>
5
+ measure: Ref<HTMLElement | null>
6
+ count: Ref<number>
7
+ contentKey?: Ref<unknown>
8
+ gap?: number
9
+ }
10
+
11
+ interface UseChipOverflow {
12
+ visibleCount: Ref<number>
13
+ hiddenCount: ComputedRef<number>
14
+ }
15
+
16
+ export function useChipOverflow(options: UseChipOverflowOptions): UseChipOverflow {
17
+ const { container, measure, count, contentKey, gap = 6 } = options
18
+
19
+ const availableWidth = ref(0)
20
+ const visibleCount = ref(0)
21
+
22
+ // Ceil so a chip is only counted as fitting when it fully fits;
23
+ // sub-pixel underestimates would let flexbox squeeze visible chips into truncation.
24
+ function chipWidth(el: HTMLElement): number {
25
+ return Math.ceil(el.getBoundingClientRect().width)
26
+ }
27
+
28
+ function recompute() {
29
+ const total = count.value
30
+ if (total <= 0) {
31
+ visibleCount.value = 0
32
+ return
33
+ }
34
+
35
+ const avail = availableWidth.value
36
+ const root = measure.value
37
+
38
+ if (!avail || !root) {
39
+ visibleCount.value = total
40
+ return
41
+ }
42
+
43
+ const chips = (Array.from(root.children) as HTMLElement[]).slice(0, total)
44
+
45
+ let used = 0
46
+ let fit = 0
47
+ for (let i = 0; i < chips.length; i++) {
48
+ const width = chipWidth(chips[i]) + (i > 0 ? gap : 0)
49
+ if (used + width > avail) break
50
+ used += width
51
+ fit++
52
+ }
53
+
54
+ if (fit >= total) {
55
+ visibleCount.value = total
56
+ return
57
+ }
58
+
59
+ const badge = root.children[total] as HTMLElement | undefined
60
+ const badgeWidth = (badge ? chipWidth(badge) : 0) + gap
61
+ while (fit > 1 && used + badgeWidth > avail) {
62
+ used -= chipWidth(chips[fit - 1]) + gap
63
+ fit--
64
+ }
65
+
66
+ visibleCount.value = Math.max(1, fit)
67
+ }
68
+
69
+ let resizeObserver: ResizeObserver | null = null
70
+
71
+ onMounted(() => {
72
+ if (container.value) {
73
+ availableWidth.value = Math.floor(container.value.clientWidth)
74
+ resizeObserver = new ResizeObserver((entries) => {
75
+ availableWidth.value = Math.floor(entries[0]?.contentRect.width ?? 0)
76
+ })
77
+ resizeObserver.observe(container.value)
78
+ }
79
+ recompute()
80
+ })
81
+
82
+ onUnmounted(() => resizeObserver?.disconnect())
83
+
84
+ watch(
85
+ contentKey ? [availableWidth, count, contentKey] : [availableWidth, count],
86
+ () => nextTick(recompute),
87
+ )
88
+
89
+ const hiddenCount = computed(() => Math.max(0, count.value - visibleCount.value))
90
+
91
+ return { visibleCount, hiddenCount }
92
+ }
@@ -9,12 +9,9 @@ import IconBlock from '#adata-ui/icons/block.vue'
9
9
  import IconDollar from '#adata-ui/icons/currency/currency-dollar.vue'
10
10
  import IconWork from '#adata-ui/icons/work-bag.vue'
11
11
  import IconDocument from '#adata-ui/icons/hdocument.vue'
12
- import IconCheck from '#adata-ui/icons/hcheck.vue'
13
- import IconFile from '#adata-ui/icons/file/file.vue'
14
12
  import IconCheckCircle from '#adata-ui/icons/check/check-circle.vue'
15
13
  import IconCar from '#adata-ui/icons/car.vue'
16
14
  import IconTruck from '#adata-ui/icons/truck.vue'
17
- import IconClipboardText from '#adata-ui/icons/clipboard-text.vue'
18
15
  import IconArrowGraph from '#adata-ui/icons/arrow/arrow-graph-up.vue'
19
16
  import IconMedal from '#adata-ui/icons/medal.vue'
20
17
  import IconCompany from '#adata-ui/icons/company.vue'
@@ -26,24 +23,27 @@ import { buildLocalizedUrl } from '#adata-ui/utils/localizedNavigation'
26
23
  import IconLock from '#adata-ui/icons/lock.vue'
27
24
  import IconReceipt from '#adata-ui/icons/receipt.vue'
28
25
  import IconFavorite from '#adata-ui/icons/bookmark/bookmark.vue'
29
- // import IconReport from '#adata-ui/icons/file/file.vue'
30
26
  import IconHistory from '#adata-ui/icons/history.vue'
31
27
  import IconMessage from '#adata-ui/icons/message/message.vue'
28
+ import AIconBriefcase from '#adata-ui/icons/briefcase.vue'
29
+ import AIconCarSide from '#adata-ui/icons/car-side.vue'
30
+ import AIconShieldVerified from '#adata-ui/icons/shield-verified.vue'
31
+ import AIconCart from '#adata-ui/icons/cart.vue'
32
32
  import {
33
- AIconWorkBag,
34
33
  AIconUsersThree,
35
- AIconReceipt,
36
- AIconCar,
37
34
  AIconArrowGraphUp,
38
35
  AIconGlobe,
39
- AIconId,
40
- AIconFiles,
41
- AIconArrowSquareDown, AIconExpandWindow, AIconUsers, AIconWarningTriangle, AIconSearch, AIconAkimat, AIconCurrencyTenge, AIconExcelIcon
36
+ AIconArrowSquareDown,
37
+ AIconExpandWindow,
38
+ AIconUsers,
39
+ AIconWarningTriangle,
40
+ AIconSearch,
41
+ AIconAkimat,
42
+ AIconCurrencyTenge,
43
+ AIconExcelIcon, AIconFile,
42
44
  } from '#components'
43
45
  import MapPinRect from '#adata-ui/icons/map/map-pin-rect.vue'
44
46
  import MapPaper from '#adata-ui/icons/map-paper.vue'
45
- import ChartBar from '#adata-ui/icons/chart-bar.vue'
46
- import Bank from '#adata-ui/icons/bank.vue'
47
47
  import { useUrls } from '#adata-ui/composables/useUrls'
48
48
  import AiAssistant from '#adata-ui/icons/ai-assistant.vue'
49
49
  import Tasks from '#adata-ui/icons/tasks.vue'
@@ -61,7 +61,7 @@ export const useHeaderNavigationLinks = () => {
61
61
  key: 'pk',
62
62
  name: t('header.products.counterparties.label'),
63
63
  link: buildLocalizedUrl(locale, urls.pk, PAGES.pk.main),
64
- icon: AIconUsersThree,
64
+ icon: AIconUsers,
65
65
  to: urls.pk,
66
66
  data_attribute: 'navigation-menu-counterparty-block',
67
67
  items: [
@@ -115,7 +115,7 @@ export const useHeaderNavigationLinks = () => {
115
115
  key: 'fines',
116
116
  name: t('header.products.fines.label'),
117
117
  link: buildLocalizedUrl(locale, urls.avto, PAGES.fines.main),
118
- icon: AIconCar,
118
+ icon: AIconCarSide,
119
119
  data_attribute: 'navigation-menu-fines-block',
120
120
  items: [
121
121
  {
@@ -142,7 +142,7 @@ export const useHeaderNavigationLinks = () => {
142
142
  key: 'work',
143
143
  name: t('header.products.jobs.label'),
144
144
  link: urls.work,
145
- icon: AIconWorkBag,
145
+ icon: AIconBriefcase,
146
146
  data_attribute: 'navigation-menu-work-block',
147
147
  items: [
148
148
  {
@@ -216,7 +216,7 @@ export const useHeaderNavigationLinks = () => {
216
216
  key: 'tenders',
217
217
  name: t('header.products.tenders.label'),
218
218
  link: urls.zakupki,
219
- icon: AIconReceipt,
219
+ icon: AIconCart,
220
220
  is_new: true,
221
221
  to: urls.tender,
222
222
  data_attribute: 'navigation-menu-zakupki-block',
@@ -264,15 +264,39 @@ export const useHeaderNavigationLinks = () => {
264
264
  is_new: true,
265
265
  name: t('header.products.edo.label'),
266
266
  link: buildLocalizedUrl(locale, urls.edo_docs , ''),
267
- icon: AIconFiles,
267
+ icon: AIconFile,
268
268
  data_attribute: 'navigation-menu-edo-block',
269
269
  items: [
270
270
  {
271
- title: t('header.products.edo.items.l.t'),
272
- subtitle: t('header.products.edo.items.l.t'),
273
- icon: AIconFiles,
274
- to: buildLocalizedUrl(locale, urls.edo_docs , '')
275
- }
271
+ title: t('header.products.edo.items.docSign.t'),
272
+ subtitle: t('header.products.edo.items.docSign.st'),
273
+ icon: AIconUsers,
274
+ to: buildLocalizedUrl(locale, urls.edo_docs , PAGES.edo.docSign)
275
+ },
276
+ {
277
+ title: t('header.products.edo.items.docTemplate.t'),
278
+ subtitle: t('header.products.edo.items.docTemplate.st'),
279
+ icon: AIconUsers,
280
+ to: buildLocalizedUrl(locale, urls.edo_docs , PAGES.edo.docTemplate)
281
+ },
282
+ {
283
+ title: t('header.products.edo.items.docRisk.t'),
284
+ subtitle: t('header.products.edo.items.docRisk.st'),
285
+ icon: AIconUsers,
286
+ to: buildLocalizedUrl(locale, urls.edo_docs , PAGES.edo.docRisk)
287
+ },
288
+ {
289
+ title: t('header.products.edo.items.docCompare.t'),
290
+ subtitle: t('header.products.edo.items.docCompare.st'),
291
+ icon: AIconUsers,
292
+ to: buildLocalizedUrl(locale, urls.edo_docs , PAGES.edo.docCompare)
293
+ },
294
+ {
295
+ title: t('header.products.edo.items.docAi.t'),
296
+ subtitle: t('header.products.edo.items.docAi.st'),
297
+ icon: AIconUsers,
298
+ to: buildLocalizedUrl(locale, urls.edo_docs , PAGES.edo.docAi)
299
+ },
276
300
  ]
277
301
  },
278
302
  {
@@ -280,7 +304,7 @@ export const useHeaderNavigationLinks = () => {
280
304
  is_new: true,
281
305
  name: t('header.products.compliance.label'),
282
306
  link: buildLocalizedUrl(locale, urls.compliance, PAGES.compliance.l),
283
- icon: AIconId,
307
+ icon: AIconShieldVerified,
284
308
  data_attribute: 'navigation-menu-compliance-block',
285
309
  items: [
286
310
  {
@@ -352,6 +376,12 @@ export const useHeaderNavigationLinks = () => {
352
376
  subtitle: t('header.products.analytics.items.subjects.subtitle'),
353
377
  icon: IconCompany,
354
378
  to: buildLocalizedUrl(locale, urls.analytics, PAGES.analytics.business)
379
+ },
380
+ {
381
+ title: t('header.products.analytics.items.demography.title'),
382
+ subtitle: t('header.products.analytics.items.demography.subtitle'),
383
+ icon: IconCompany,
384
+ to: buildLocalizedUrl(locale, urls.analytics, PAGES.analytics.demography)
355
385
  }
356
386
  ]
357
387
  },
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+
3
+ </script>
4
+
5
+ <template>
6
+ <svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
7
+ <path d="M3.125 7.5H11.875" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
8
+ <path d="M7.5 3.125L11.875 7.5L7.5 11.875" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
9
+ </svg>
10
+ </template>
11
+
12
+ <style scoped>
13
+
14
+ </style>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+
3
+ </script>
4
+
5
+ <template>
6
+ <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
7
+ <path d="M15 5.25H3C2.17157 5.25 1.5 5.92157 1.5 6.75V14.25C1.5 15.0784 2.17157 15.75 3 15.75H15C15.8284 15.75 16.5 15.0784 16.5 14.25V6.75C16.5 5.92157 15.8284 5.25 15 5.25Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
8
+ <path d="M12 15.75V3.75C12 3.35218 11.842 2.97064 11.5607 2.68934C11.2794 2.40804 10.8978 2.25 10.5 2.25H7.5C7.10218 2.25 6.72064 2.40804 6.43934 2.68934C6.15804 2.97064 6 3.35218 6 3.75V15.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
9
+ </svg>
10
+ </template>
11
+
12
+ <style scoped>
13
+
14
+ </style>