adata-ui 2.0.38 → 2.0.40

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 (46) hide show
  1. package/.nuxtrc +1 -1
  2. package/.playground/app.config.ts +5 -5
  3. package/README.md +75 -75
  4. package/app.config.ts +1 -0
  5. package/components/elements/README.md +1 -1
  6. package/components/features/payment/banner/PaymentBanner.vue +69 -0
  7. package/components/features/payment/process/PaymentKaspiQrSidePanel.vue +158 -0
  8. package/components/features/payment/process/PaymentKaspiRedirectSidePanel.vue +112 -0
  9. package/components/features/payment/process/PaymentMethodSidePanel.vue +117 -0
  10. package/components/features/payment/process/PaymentProcess.vue +136 -0
  11. package/components/features/payment/process/PaymentTopUpSidePanel.vue +113 -0
  12. package/components/forms/README.md +1 -1
  13. package/components/modals/AConfirmationEmail.vue +40 -40
  14. package/components/modals/ContentNavigationModal.vue +5 -5
  15. package/components/modals/Resend.vue +81 -81
  16. package/components/modals/id/IdBanner.vue +58 -0
  17. package/components/modals/id/IdConfirmAccountOtpModal.vue +2 -6
  18. package/components/modals/id/IdLoginModal.vue +2 -6
  19. package/components/modals/id/IdModals.vue +1 -1
  20. package/components/modals/id/IdNewPasswordModal.vue +2 -6
  21. package/components/modals/id/IdRecoveryModal.vue +2 -6
  22. package/components/modals/id/IdRegistrationModal.vue +2 -8
  23. package/components/modals/id/IdResetPasswordOtpModal.vue +2 -6
  24. package/components/modals/id/IdTwoFactorModal.vue +2 -6
  25. package/components/navigation/README.md +1 -1
  26. package/components/overlays/README.md +1 -1
  27. package/components/overlays/side-panel/ASidePanel.vue +439 -0
  28. package/composables/useBuyTariffs.ts +91 -91
  29. package/composables/useHeaderNavigationLinks.ts +12 -12
  30. package/composables/useIdModals.ts +8 -0
  31. package/composables/usePayment.ts +72 -0
  32. package/icons/google.vue +41 -41
  33. package/icons/kaspi-qr.vue +13 -0
  34. package/icons/linkedin.vue +24 -24
  35. package/icons/mailru.vue +34 -34
  36. package/icons/sun.vue +14 -14
  37. package/icons/yandex.vue +28 -28
  38. package/lang/en.ts +46 -0
  39. package/lang/kk.ts +46 -0
  40. package/lang/ru.ts +46 -0
  41. package/layouts/default.vue +13 -13
  42. package/nuxt.config.ts +13 -1
  43. package/package.json +5 -5
  44. package/public/kaspi/logo.svg +4 -0
  45. package/stores/auth.store.ts +0 -12
  46. /package/components/{modals/id/helpers → utils}/removeTrailingSlash.ts +0 -0
package/.nuxtrc CHANGED
@@ -1 +1 @@
1
- typescript.includeWorkspace = true
1
+ typescript.includeWorkspace = true
@@ -1,5 +1,5 @@
1
- export default defineAppConfig({
2
- myLayer: {
3
- name: 'My amazing Nuxt layer (overwritten)'
4
- }
5
- })
1
+ export default defineAppConfig({
2
+ myLayer: {
3
+ name: 'My amazing Nuxt layer (overwritten)'
4
+ }
5
+ })
package/README.md CHANGED
@@ -1,75 +1,75 @@
1
- # Adata UI with Nuxt 3 using Layers
2
-
3
- Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
4
-
5
- ## Setup
6
-
7
- Make sure to install the dependencies:
8
-
9
- ```bash
10
- # npm
11
- npm install
12
-
13
- # pnpm
14
- pnpm install
15
-
16
- # yarn
17
- yarn install
18
-
19
- # bun
20
- bun install
21
- ```
22
-
23
- ## Development Server
24
-
25
- Start the development server on `https://localhost:3000`:
26
-
27
- ```bash
28
- # npm
29
- npm run dev
30
-
31
- # pnpm
32
- pnpm run dev
33
-
34
- # yarn
35
- yarn dev
36
-
37
- # bun
38
- bun run dev
39
- ```
40
-
41
- ## Production
42
-
43
- Build the application for production:
44
-
45
- ```bash
46
- # npm
47
- npm run build
48
-
49
- # pnpm
50
- pnpm run build
51
-
52
- # yarn
53
- yarn build
54
-
55
- # bun
56
- bun run build
57
- ```
58
-
59
- Locally preview production build:
60
-
61
- ```bash
62
- # npm
63
- npm run preview
64
-
65
- # pnpm
66
- pnpm run preview
67
-
68
- # yarn
69
- yarn preview
70
-
71
- # bun
72
- bun run preview
73
- ```
74
-
75
- Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
1
+ # Adata UI with Nuxt 3 using Layers
2
+
3
+ Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
4
+
5
+ ## Setup
6
+
7
+ Make sure to install the dependencies:
8
+
9
+ ```bash
10
+ # npm
11
+ npm install
12
+
13
+ # pnpm
14
+ pnpm install
15
+
16
+ # yarn
17
+ yarn install
18
+
19
+ # bun
20
+ bun install
21
+ ```
22
+
23
+ ## Development Server
24
+
25
+ Start the development server on `https://localhost:3000`:
26
+
27
+ ```bash
28
+ # npm
29
+ npm run dev
30
+
31
+ # pnpm
32
+ pnpm run dev
33
+
34
+ # yarn
35
+ yarn dev
36
+
37
+ # bun
38
+ bun run dev
39
+ ```
40
+
41
+ ## Production
42
+
43
+ Build the application for production:
44
+
45
+ ```bash
46
+ # npm
47
+ npm run build
48
+
49
+ # pnpm
50
+ pnpm run build
51
+
52
+ # yarn
53
+ yarn build
54
+
55
+ # bun
56
+ bun run build
57
+ ```
58
+
59
+ Locally preview production build:
60
+
61
+ ```bash
62
+ # npm
63
+ npm run preview
64
+
65
+ # pnpm
66
+ pnpm run preview
67
+
68
+ # yarn
69
+ yarn preview
70
+
71
+ # bun
72
+ bun run preview
73
+ ```
74
+
75
+ Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
package/app.config.ts CHANGED
@@ -23,6 +23,7 @@ declare module '@nuxt/schema' {
23
23
  counterParty?: string
24
24
  langIsOn?: boolean
25
25
  authMode?: 'local' | 'separate'
26
+ cloudPayments?: string
26
27
  }
27
28
  }
28
29
  }
@@ -1 +1 @@
1
- # button, alerts, dropdown
1
+ # button, alerts, dropdown
@@ -0,0 +1,69 @@
1
+ <script setup lang="ts">
2
+ import { buildLocalizedUrl } from '#adata-ui/utils/localizedNavigation'
3
+ import PaymentProcess from '#adata-ui/components/features/payment/process/PaymentProcess.vue'
4
+
5
+ const { t, locale } = useI18n()
6
+ const { myLayer } = useAppConfig()
7
+
8
+ const { topUpSidePanel } = usePayment()
9
+
10
+ const landingUrl = myLayer.landingUrl
11
+
12
+ function onBuy() {
13
+ topUpSidePanel.value = true
14
+ }
15
+ </script>
16
+
17
+ <template>
18
+ <div class="gradient flex justify-between rounded-lg p-4 ring-1 ring-inset ring-blue-700/80 dark:bg-gray-800">
19
+ <div>
20
+ <p class="mb-2 font-semibold">
21
+ {{ t('payment.banner.title') }}
22
+ </p>
23
+ <i18n-t
24
+ keypath="payment.banner.subtitle"
25
+ tag="p"
26
+ class="text-sm text-gray-600 dark:text-gray-200"
27
+ >
28
+ <template #tariffs>
29
+ <nuxt-link
30
+ class="font-semibold text-blue-700 dark:text-blue-500"
31
+ :to="buildLocalizedUrl(locale, landingUrl, '/tariffs')"
32
+ >
33
+ {{ t('payment.banner.tariffs') }}
34
+ </nuxt-link>
35
+ </template>
36
+ </i18n-t>
37
+ </div>
38
+
39
+ <a-button
40
+ size="md"
41
+ class="self-end"
42
+ @click="onBuy"
43
+ >
44
+ {{ t('actions.buy') }}
45
+ </a-button>
46
+ </div>
47
+
48
+ <payment-process />
49
+ </template>
50
+
51
+ <style scoped>
52
+ .gradient {
53
+ background: linear-gradient(
54
+ 239.71deg,
55
+ #B3D5F9 -7.48%,
56
+ #E6F1FD 39.62%,
57
+ #CCE2FB 85.82%
58
+ );
59
+ }
60
+
61
+ .dark .gradient {
62
+ background: linear-gradient(
63
+ 239.71deg,
64
+ #17303F -7.48%,
65
+ #161617 39.62%,
66
+ #17303F 85.82%
67
+ );
68
+ }
69
+ </style>
@@ -0,0 +1,158 @@
1
+ <script setup lang="ts">
2
+ import QRCode from 'qrcode'
3
+ import { removeTrailingSlash } from '#adata-ui/components/utils/removeTrailingSlash'
4
+
5
+ const props = defineProps<{
6
+ requestUrl: string
7
+ requestId: number
8
+ }>()
9
+
10
+ const emit = defineEmits<{
11
+ (e: 'back', type: 'kaspi'): void
12
+ (e: 'updateUserRate'): void
13
+ }>()
14
+
15
+ const isOpen = defineModel({ default: false })
16
+
17
+ const { t, locale } = useI18n()
18
+ const { commonAuth } = useAppConfig()
19
+ const accessToken = useCookie('accessToken')
20
+ const colorMode = useColorMode()
21
+
22
+ const userApiURL = commonAuth.userApiURL
23
+
24
+ const paymentSuccess = ref(false)
25
+ let intervalId: NodeJS.Timeout | null = null
26
+
27
+ function onBack() {
28
+ emit('back', 'kaspi')
29
+ }
30
+
31
+ async function checkPayment() {
32
+ try {
33
+ const { data } = await $fetch(`${removeTrailingSlash(userApiURL)}/user/kaspi-balance/invoice-status`, {
34
+ method: 'GET',
35
+ credentials: 'include',
36
+ headers: {
37
+ Authorization: `Bearer ${accessToken.value}`,
38
+ lang: locale.value,
39
+ },
40
+ params: {
41
+ request_id: props.requestId,
42
+ initial: 0,
43
+ },
44
+ })
45
+
46
+ if (data.status === 'completed') {
47
+ paymentSuccess.value = true
48
+ }
49
+ }
50
+ catch (e) {
51
+ console.error(e)
52
+ }
53
+ }
54
+
55
+ watch(isOpen, async (value) => {
56
+ if (!value) {
57
+ if (intervalId) {
58
+ clearInterval(intervalId)
59
+ }
60
+ return
61
+ }
62
+
63
+ await nextTick()
64
+
65
+ const canvas = document.getElementById('kaspiQr') as HTMLCanvasElement | null
66
+ if (!canvas) return
67
+
68
+ QRCode.toCanvas(
69
+ canvas,
70
+ props.requestUrl,
71
+ {
72
+ errorCorrectionLevel: 'H',
73
+ width: 300,
74
+ margin: 0,
75
+ color: {
76
+ dark: colorMode.value === 'dark' ? '#FFFFFF' : '#000000', // квадраты
77
+ light: colorMode.value === 'dark' ? '#000000' : '#FFFFFF' // фон
78
+ }
79
+ },
80
+ (error) => {
81
+
82
+ if (error) {
83
+ console.error(error)
84
+ return
85
+ }
86
+
87
+ const ctx = canvas.getContext('2d')
88
+ if (!ctx) return
89
+
90
+ const logo = new Image()
91
+ logo.src = '/kaspi/logo.svg'
92
+ logo.onload = () => {
93
+ const size = canvas.width * 0.2
94
+ const x = (canvas.width - size) / 2
95
+ const y = (canvas.height - size) / 2
96
+
97
+ ctx.fillStyle = colorMode.value === 'dark' ? '#000000' : '#fff'
98
+ ctx.fillRect(x - 6, y - 6, size + 12, size + 12)
99
+
100
+ ctx.drawImage(logo, x, y, size, size)
101
+ }
102
+ })
103
+
104
+ intervalId = setInterval(() => {
105
+ if (paymentSuccess.value && intervalId) {
106
+ clearInterval(intervalId)
107
+ emit('updateUserRate')
108
+ return
109
+ }
110
+ checkPayment()
111
+ }, 1000)
112
+ })
113
+
114
+ </script>
115
+
116
+ <template>
117
+ <a-side-panel v-model="isOpen" width="484px">
118
+ <template #header>
119
+ <div class="flex items-center gap-2">
120
+ <button @click="onBack">
121
+ <a-icon-chevron-left class="size-6" />
122
+ </button>
123
+ <p class="text-xl font-semibold">
124
+ {{ t('payment.kaspi.title') }}
125
+ </p>
126
+ </div>
127
+ </template>
128
+
129
+ <div class="flex flex-col gap-6">
130
+ <div class="flex flex-col items-center text-center text-black dark:text-white">
131
+ <p class="mb-4 font-semibold text-sm">
132
+ {{ t('payment.kaspi.description') }}
133
+ </p>
134
+
135
+ <div class="flex gap-3 items-center">
136
+ <a-icon-kaspi-qr class="size-16" />
137
+ <span class="font-bold text-[44px]">
138
+ {{ t('payment.kaspi.qr') }}
139
+ </span>
140
+ </div>
141
+
142
+ <p class="mt-5 font-bold text-2xl">{{ t('payment.kaspi.scan') }}</p>
143
+
144
+ <canvas class="mt-5" id="kaspiQr"></canvas>
145
+
146
+ <p class="mt-10 text-lg">{{ t('payment.kaspi.adata') }}</p>
147
+ </div>
148
+
149
+ <a-button @click="onBack" view="outline">
150
+ {{ t('payment.kaspi.changeMethod') }}
151
+ </a-button>
152
+ </div>
153
+ </a-side-panel>
154
+ </template>
155
+
156
+ <style scoped>
157
+
158
+ </style>
@@ -0,0 +1,112 @@
1
+ <script setup lang="ts">
2
+ import { removeTrailingSlash } from '#adata-ui/components/utils/removeTrailingSlash'
3
+
4
+ const props = defineProps<{
5
+ requestId: number
6
+ }>()
7
+
8
+ const emit = defineEmits<{
9
+ (e: 'back', type: 'kaspi'): void
10
+ (e: 'updateUserRate'): void
11
+ }>()
12
+
13
+ const isOpen = defineModel({ default: false })
14
+
15
+ const { commonAuth } = useAppConfig()
16
+ const { t, locale } = useI18n()
17
+ const localePath = useLocalePath()
18
+ const accessToken = useCookie('accessToken')
19
+
20
+ const userApiURL = commonAuth.userApiURL
21
+
22
+ const paymentSuccess = ref(false)
23
+ let intervalId: NodeJS.Timeout | null = null
24
+
25
+ async function checkPayment() {
26
+ try {
27
+ const { data } = await $fetch(`${removeTrailingSlash(userApiURL)}/user/kaspi-balance/invoice-status`, {
28
+ method: 'GET',
29
+ credentials: 'include',
30
+ headers: {
31
+ Authorization: `Bearer ${accessToken.value}`,
32
+ lang: locale.value,
33
+ },
34
+ params: {
35
+ request_id: props.requestId,
36
+ initial: 0,
37
+ },
38
+ })
39
+
40
+ if (data.status === 'completed') {
41
+ paymentSuccess.value = true
42
+ }
43
+ }
44
+ catch (e) {
45
+ console.error(e)
46
+ }
47
+ }
48
+
49
+ function goKaspi() {
50
+ window.open(localePath(`https://kaspi.kz/pay/adata?service_id=5964&9507=${props.requestId}`), '_blank')
51
+ }
52
+
53
+ function onBack() {
54
+ emit('back', 'kaspi')
55
+ }
56
+
57
+ watch(isOpen, async (value) => {
58
+ if (!value) {
59
+ if (intervalId) {
60
+ clearInterval(intervalId)
61
+ }
62
+ return
63
+ }
64
+
65
+ intervalId = setInterval(() => {
66
+ if (paymentSuccess.value && intervalId) {
67
+ clearInterval(intervalId)
68
+ emit('updateUserRate')
69
+ return
70
+ }
71
+ checkPayment()
72
+ }, 1000)
73
+ })
74
+ </script>
75
+
76
+ <template>
77
+ <a-side-panel
78
+ v-model="isOpen"
79
+ width="484px"
80
+ >
81
+ <div class="flex flex-col gap-5">
82
+ <p class="text-center text-2xl font-bold whitespace-pre-wrap">
83
+ {{ t('payment.redirect.title') }}
84
+ </p>
85
+ <a-button block @click="goKaspi">
86
+ {{ t('payment.redirect.goKaspi') }}
87
+ </a-button>
88
+ <div class="flex flex-col gap-2">
89
+ <p class="text-center text-sm">
90
+ {{ t('payment.redirect.paymentId') }}
91
+ </p>
92
+ <p class="text-center text-xl font-semibold">
93
+ {{ requestId }}
94
+ </p>
95
+ </div>
96
+ <p class="text-center text-sm">
97
+ {{ t('payment.redirect.description') }}
98
+ </p>
99
+ <a-button
100
+ view="outline"
101
+ block
102
+ @click="onBack"
103
+ >
104
+ {{ t('payment.redirect.changeMethod') }}
105
+ </a-button>
106
+ </div>
107
+ </a-side-panel>
108
+ </template>
109
+
110
+ <style scoped>
111
+
112
+ </style>
@@ -0,0 +1,117 @@
1
+ <script setup lang="ts">
2
+ import { AIconPaymentCard, AIconPaymentKaspi } from '#components'
3
+
4
+ type IBank = 'kaspi' | 'other'
5
+
6
+ const props = defineProps<{
7
+ sum: number
8
+ }>()
9
+
10
+ const emit = defineEmits<{
11
+ (e: 'nextBank', bank: IBank, sum: number): void
12
+ (e: 'back', type: 'method'): void
13
+ }>()
14
+
15
+ const isOpen = defineModel({ default: false })
16
+
17
+ const { t } = useI18n()
18
+
19
+ const checkbox = ref<IBank>('kaspi')
20
+ const cards = [
21
+ {
22
+ id: 'kaspi',
23
+ name: 'payment.method.kaspi',
24
+ sum: 10000,
25
+ img: AIconPaymentKaspi,
26
+ },
27
+ {
28
+ id: 'other',
29
+ name: 'payment.method.other',
30
+ sum: 10000,
31
+ img: AIconPaymentCard,
32
+ },
33
+ ]
34
+
35
+ function confirm() {
36
+ emit('nextBank', checkbox.value, props.sum)
37
+ }
38
+
39
+ function cancel() {
40
+ isOpen.value = false
41
+ }
42
+
43
+ function onBack() {
44
+ emit('back', 'method')
45
+ }
46
+ </script>
47
+
48
+ <template>
49
+ <a-side-panel
50
+ v-model="isOpen"
51
+ width="484px"
52
+ >
53
+ <template #header>
54
+ <div class="flex items-center gap-2">
55
+ <button @click="onBack">
56
+ <a-icon-chevron-left class="size-6" />
57
+ </button>
58
+ <p class="text-xl font-semibold">
59
+ {{ t('payment.method.title') }}
60
+ </p>
61
+ </div>
62
+ </template>
63
+
64
+ <div class="flex flex-col gap-6">
65
+ <div class="flex flex-col items-center gap-4">
66
+ <a-ill-phone-check class="size-[120px]" />
67
+ <p class="text-center text-sm font-semibold">
68
+ {{ t('payment.method.description') }}
69
+ </p>
70
+ </div>
71
+
72
+ <div class="font-semibold">
73
+ {{ t('payment.method.note') }}
74
+ </div>
75
+
76
+ <div class="flex flex-col gap-2">
77
+ <a-radio-button
78
+ v-for="(item) in cards"
79
+ :key="item.id"
80
+ v-model="checkbox"
81
+ :name="`${item.name}`"
82
+ side="right"
83
+ size="lg"
84
+ :value="item.id"
85
+ class="flex items-center justify-between gap-2 rounded-md bg-gray-50 p-[10px_16px] dark:bg-[#393D40]"
86
+ >
87
+ <div class="flex w-full items-center gap-2">
88
+ <component :is="item.img" />
89
+ <div class="flex w-full items-center justify-between">
90
+ {{ t(item.name) }}
91
+ <p class="body-600">
92
+ {{ Math.round(sum).toLocaleString('RU-ru') }} ₸
93
+ </p>
94
+ </div>
95
+ </div>
96
+ </a-radio-button>
97
+ </div>
98
+
99
+ <div class="flex flex-col gap-2 ">
100
+ <a-button block @click="confirm">
101
+ {{ t('actions.topUp') }}
102
+ </a-button>
103
+ <a-button
104
+ view="outline"
105
+ block
106
+ @click="cancel"
107
+ >
108
+ {{ t('actions.close') }}
109
+ </a-button>
110
+ </div>
111
+ </div>
112
+ </a-side-panel>
113
+ </template>
114
+
115
+ <style scoped>
116
+
117
+ </style>