adata-ui 2.0.23 → 2.0.25
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/components/elements/curve-block/ACurveBlock.vue +3 -6
- package/components/elements/select/ASelect.vue +50 -5
- package/components/modals/id/IdConfirmAccountOtpModal.vue +147 -0
- package/components/modals/id/IdConfirmSuccessfulModal.vue +25 -0
- package/components/modals/id/IdLoginModal.vue +150 -131
- package/components/modals/id/IdModals.vue +41 -7
- package/components/modals/id/IdNewPasswordModal.vue +55 -62
- package/components/modals/id/IdPasswordSuccessfulModal.vue +15 -16
- package/components/modals/id/IdRecoveryModal.vue +39 -34
- package/components/modals/id/IdRegistrationModal.vue +75 -103
- package/components/modals/id/IdResetPasswordOtpModal.vue +154 -0
- package/components/modals/two-factor/otp-input.vue +1 -1
- package/components/navigation/footer/NewFooter.vue +3 -2
- package/components/navigation/header/AlmatyContacts.vue +3 -1
- package/components/navigation/header/AstanaContacts.vue +3 -1
- package/composables/useIdModals.ts +10 -2
- package/lang/ru.ts +16 -5
- package/nuxt.config.ts +1 -0
- package/package.json +4 -1
- package/stores/auth.store.ts +12 -0
- package/components/modals/Accept.vue +0 -45
- package/components/modals/id/IdEmailModal.vue +0 -29
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import OtpInput from '#adata-ui/components/modals/two-factor/otp-input.vue'
|
|
3
|
+
import { useAuthStore } from '#adata-ui/stores/auth.store'
|
|
4
|
+
|
|
5
|
+
const { $toast } = useNuxtApp()
|
|
6
|
+
const { t, locale } = useI18n()
|
|
7
|
+
const { commonAuth } = useAppConfig()
|
|
8
|
+
|
|
9
|
+
const authStore = useAuthStore()
|
|
10
|
+
const { intermediateState } = storeToRefs(authStore)
|
|
11
|
+
|
|
12
|
+
const { resetPasswordOtpModal, newPasswordModal } = useIdModals()
|
|
13
|
+
|
|
14
|
+
const authApiURL = commonAuth.authApiURL
|
|
15
|
+
|
|
16
|
+
const otp = ref(['', '', '', '', '', ''])
|
|
17
|
+
const otpFormatted = computed(() => {
|
|
18
|
+
return otp.value.join('')
|
|
19
|
+
})
|
|
20
|
+
const showError = ref(false)
|
|
21
|
+
const isLoading = ref(false)
|
|
22
|
+
|
|
23
|
+
async function onConfirm() {
|
|
24
|
+
try {
|
|
25
|
+
isLoading.value = true
|
|
26
|
+
|
|
27
|
+
const response = await $fetch(`${authApiURL}/password/validate-otp`, {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
credentials: 'include',
|
|
30
|
+
headers: {
|
|
31
|
+
lang: locale.value,
|
|
32
|
+
},
|
|
33
|
+
body: {
|
|
34
|
+
email: intermediateState.value.email,
|
|
35
|
+
otp: otpFormatted.value,
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
intermediateState.value.token = response.data
|
|
40
|
+
intermediateState.value.otp = otpFormatted.value
|
|
41
|
+
|
|
42
|
+
resetPasswordOtpModal.value = false
|
|
43
|
+
newPasswordModal.value = true
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
showError.value = true
|
|
47
|
+
$toast.error(error.data.message)
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
isLoading.value = false
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function onResend() {
|
|
55
|
+
try {
|
|
56
|
+
await $fetch(`${authApiURL}/password/email-otp`, {
|
|
57
|
+
method: 'POST',
|
|
58
|
+
credentials: 'include',
|
|
59
|
+
headers: {
|
|
60
|
+
lang: locale.value,
|
|
61
|
+
},
|
|
62
|
+
body: {
|
|
63
|
+
email: intermediateState.value.email,
|
|
64
|
+
},
|
|
65
|
+
})
|
|
66
|
+
runTimer()
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
$toast.error(error.data.message)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function onClose() {
|
|
74
|
+
otp.value = ['', '', '', '', '', '']
|
|
75
|
+
showError.value = false
|
|
76
|
+
resetPasswordOtpModal.value = false
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function handleEnter(e: KeyboardEvent) {
|
|
80
|
+
if (e.key === 'Enter') {
|
|
81
|
+
onConfirm()
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const timer = ref(60)
|
|
86
|
+
|
|
87
|
+
function runTimer() {
|
|
88
|
+
const intervalId = setInterval(() => {
|
|
89
|
+
if (!timer.value) clearInterval(intervalId)
|
|
90
|
+
return timer.value--
|
|
91
|
+
}, 1000)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
onMounted(() => {
|
|
95
|
+
runTimer()
|
|
96
|
+
document.addEventListener('keyup', handleEnter)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
onBeforeUnmount(() => {
|
|
100
|
+
document.removeEventListener('keyup', handleEnter)
|
|
101
|
+
})
|
|
102
|
+
</script>
|
|
103
|
+
|
|
104
|
+
<template>
|
|
105
|
+
<div class="flex flex-col items-center gap-4 text-center">
|
|
106
|
+
<h2 class="text-2xl font-bold">
|
|
107
|
+
{{ t('modals.id.resetPasswordOtp.title') }}
|
|
108
|
+
</h2>
|
|
109
|
+
|
|
110
|
+
<a-icon-hand-with-phone-light class="size-32 dark:hidden" />
|
|
111
|
+
<a-icon-hand-with-phone-dark class="hidden size-32 dark:block" />
|
|
112
|
+
|
|
113
|
+
<div class="text-sm">
|
|
114
|
+
<p class="mb-1">
|
|
115
|
+
{{ t('modals.id.resetPasswordOtp.content') }}
|
|
116
|
+
</p>
|
|
117
|
+
|
|
118
|
+
<div v-if="timer > 0" class="text-2xl font-bold">
|
|
119
|
+
{{ timer }} {{ t('register.modal.seconds') }}
|
|
120
|
+
</div>
|
|
121
|
+
<button
|
|
122
|
+
v-else
|
|
123
|
+
class="text-blue-700 dark:text-blue-500"
|
|
124
|
+
@click="onResend"
|
|
125
|
+
>
|
|
126
|
+
{{ t('actions.resend') }}
|
|
127
|
+
</button>
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
<otp-input v-model="otp" v-model:error="showError" />
|
|
131
|
+
|
|
132
|
+
<div class="flex w-full gap-2">
|
|
133
|
+
<a-button
|
|
134
|
+
block
|
|
135
|
+
view="outline"
|
|
136
|
+
@click="onClose"
|
|
137
|
+
>
|
|
138
|
+
{{ t('actions.close') }}
|
|
139
|
+
</a-button>
|
|
140
|
+
<a-button
|
|
141
|
+
block
|
|
142
|
+
:loading="isLoading"
|
|
143
|
+
:disabled="otpFormatted.length < 6"
|
|
144
|
+
@click="onConfirm"
|
|
145
|
+
>
|
|
146
|
+
{{ t('actions.confirm') }}
|
|
147
|
+
</a-button>
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
</template>
|
|
151
|
+
|
|
152
|
+
<style scoped>
|
|
153
|
+
|
|
154
|
+
</style>
|
|
@@ -212,8 +212,8 @@ const contactLinks = {
|
|
|
212
212
|
/>
|
|
213
213
|
</div>
|
|
214
214
|
</div>
|
|
215
|
-
|
|
216
|
-
<div class="flex flex-col gap-2 items-start">
|
|
215
|
+
<!--noindex-->
|
|
216
|
+
<div class="flex flex-col gap-2 items-start" data-nosnippet>
|
|
217
217
|
<nuxt-link
|
|
218
218
|
class="text-sm font-semibold pb-3 pr-4 border-b-[0.5px] border-white cursor-pointer"
|
|
219
219
|
:to="contactLinks.link?.replace(/\/$/, '')"
|
|
@@ -249,6 +249,7 @@ const contactLinks = {
|
|
|
249
249
|
</div>
|
|
250
250
|
</div>
|
|
251
251
|
</div>
|
|
252
|
+
<!--/noindex-->
|
|
252
253
|
</div>
|
|
253
254
|
|
|
254
255
|
<div class="lg:hidden flex gap-8 flex-wrap">
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
2
|
+
<!--noindex-->
|
|
3
|
+
<div class="h-[272px]" data-nosnippet>
|
|
3
4
|
<h2 class="heading-02 mb-4">
|
|
4
5
|
{{ t('header.contacts.almaty.title') }}
|
|
5
6
|
</h2>
|
|
@@ -89,6 +90,7 @@
|
|
|
89
90
|
<!-- </div>-->
|
|
90
91
|
</div>
|
|
91
92
|
</div>
|
|
93
|
+
<!--/noindex-->
|
|
92
94
|
</template>
|
|
93
95
|
|
|
94
96
|
<script setup lang="ts">
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
2
|
+
<!--noindex-->
|
|
3
|
+
<div class="h-[272px]" data-nosnippet>
|
|
3
4
|
<h2 class="heading-02 mb-4">
|
|
4
5
|
{{ t('header.contacts.astana.title') }}
|
|
5
6
|
</h2>
|
|
@@ -23,6 +24,7 @@
|
|
|
23
24
|
</div>
|
|
24
25
|
</div>
|
|
25
26
|
</div>
|
|
27
|
+
<!--/noindex-->
|
|
26
28
|
</template>
|
|
27
29
|
|
|
28
30
|
<script setup lang="ts">
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
export function useIdModals() {
|
|
2
2
|
const loginModal = useState('login-modal', () => false)
|
|
3
|
+
const twoFactorModal = useState('two-factor-modal', () => false)
|
|
4
|
+
|
|
3
5
|
const registrationModal = useState('registration-modal', () => false)
|
|
6
|
+
const confirmAccountOtpModal = useState('confirm-account-otp-modal', () => false)
|
|
7
|
+
const confirmSuccessfulModal = useState('confirm-successful-modal', () => false)
|
|
8
|
+
|
|
4
9
|
const recoveryModal = useState('recovery-modal', () => false)
|
|
5
|
-
const
|
|
10
|
+
const resetPasswordOtpModal = useState('reset-password-otp-modal', () => false)
|
|
6
11
|
const newPasswordModal = useState('new-password-modal', () => false)
|
|
7
12
|
const passwordSuccessfulModal = useState('password-successful-modal', () => false)
|
|
8
13
|
|
|
9
14
|
return {
|
|
10
15
|
loginModal,
|
|
16
|
+
twoFactorModal,
|
|
11
17
|
registrationModal,
|
|
18
|
+
confirmAccountOtpModal,
|
|
12
19
|
recoveryModal,
|
|
13
|
-
|
|
20
|
+
resetPasswordOtpModal,
|
|
14
21
|
newPasswordModal,
|
|
15
22
|
passwordSuccessfulModal,
|
|
23
|
+
confirmSuccessfulModal,
|
|
16
24
|
}
|
|
17
25
|
}
|
package/lang/ru.ts
CHANGED
|
@@ -470,7 +470,9 @@ const RuLocale = {
|
|
|
470
470
|
back: 'Назад',
|
|
471
471
|
recover: 'Восстановить',
|
|
472
472
|
cancel: 'Отменить',
|
|
473
|
-
|
|
473
|
+
set: 'Установить',
|
|
474
|
+
resend: 'Отправить еще раз',
|
|
475
|
+
confirm: 'Подтвердить',
|
|
474
476
|
},
|
|
475
477
|
modals: {
|
|
476
478
|
id: {
|
|
@@ -479,9 +481,9 @@ const RuLocale = {
|
|
|
479
481
|
content: 'Укажите Вашу электронную почту / номер телефона',
|
|
480
482
|
placeholder: 'Введите email или номер телефона',
|
|
481
483
|
},
|
|
482
|
-
|
|
483
|
-
title: '
|
|
484
|
-
content: '
|
|
484
|
+
resetPasswordOtp: {
|
|
485
|
+
title: 'Подтвердите действие',
|
|
486
|
+
content: 'Введите 6-значный код подтверждения отправленный на ваш адрес электронной почты',
|
|
485
487
|
},
|
|
486
488
|
newPassword: {
|
|
487
489
|
title: 'Создание нового пароля',
|
|
@@ -499,6 +501,14 @@ const RuLocale = {
|
|
|
499
501
|
confirm: 'Подтвердить',
|
|
500
502
|
error: 'Вы ввели неверный код',
|
|
501
503
|
},
|
|
504
|
+
passwordSuccessful: {
|
|
505
|
+
title: 'Отлично',
|
|
506
|
+
content: 'Вы успешно сменили пароль от учетной записи',
|
|
507
|
+
},
|
|
508
|
+
confirmSuccessful: {
|
|
509
|
+
title: 'Успешно!',
|
|
510
|
+
content: 'Электронная почта подтверждена. Спасибо!',
|
|
511
|
+
},
|
|
502
512
|
},
|
|
503
513
|
auth: {
|
|
504
514
|
title: 'Нет доступа',
|
|
@@ -678,7 +688,7 @@ const RuLocale = {
|
|
|
678
688
|
},
|
|
679
689
|
},
|
|
680
690
|
modal: {
|
|
681
|
-
title: 'Подтверждение',
|
|
691
|
+
title: 'Подтверждение аккаунта',
|
|
682
692
|
subtitle1: 'На вашу почту отправлено письмо с ссылкой на подтверждение аккаунта',
|
|
683
693
|
subtitle2: 'Ожидание подтверждения, повторно отправить письмо можно через',
|
|
684
694
|
confirmationEmail: 'Если Вы не получили письмо с подтверждением',
|
|
@@ -694,6 +704,7 @@ const RuLocale = {
|
|
|
694
704
|
user_canceled_auth: 'Вы отменили авторизацию',
|
|
695
705
|
email_not_verified: 'Почта не подтверждена',
|
|
696
706
|
email: 'Неправильный email',
|
|
707
|
+
otp: 'Вы ввели неверный код',
|
|
697
708
|
authorization_error_with_yandex:
|
|
698
709
|
'Не удалось авторизоваться через Яндекс',
|
|
699
710
|
authorization_error_with_google:
|
package/nuxt.config.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adata-ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.25",
|
|
5
5
|
"main": "./nuxt.config.ts",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "nuxi dev .playground",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"vue-tsc": "^2.2.12"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
+
"@floating-ui/vue": "^1.1.9",
|
|
37
38
|
"@headlessui/tailwindcss": "^0.2.2",
|
|
38
39
|
"@headlessui/vue": "^1.7.23",
|
|
39
40
|
"@nuxt/image": "1.8.1",
|
|
@@ -42,6 +43,7 @@
|
|
|
42
43
|
"@nuxtjs/google-fonts": "^3.2.0",
|
|
43
44
|
"@nuxtjs/i18n": "9.3.3",
|
|
44
45
|
"@nuxtjs/tailwindcss": "^6.14.0",
|
|
46
|
+
"@pinia/nuxt": "^0.11.2",
|
|
45
47
|
"@popperjs/core": "^2.11.8",
|
|
46
48
|
"@samk-dev/nuxt-vcalendar": "^1.0.4",
|
|
47
49
|
"@tailwindcss/aspect-ratio": "^0.4.2",
|
|
@@ -56,6 +58,7 @@
|
|
|
56
58
|
"lodash.isequal": "^4.5.0",
|
|
57
59
|
"maska": "^2.1.11",
|
|
58
60
|
"ofetch": "^1.4.1",
|
|
61
|
+
"pinia": "^3.0.3",
|
|
59
62
|
"sass": "^1.90.0",
|
|
60
63
|
"scss": "^0.2.4",
|
|
61
64
|
"tailwind-merge": "^2.6.0",
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
|
|
3
|
-
defineEmits<{ (e: 'back'): void, (e: 'repeated'): void }>()
|
|
4
|
-
|
|
5
|
-
const timer = ref(60)
|
|
6
|
-
|
|
7
|
-
function runTimer() {
|
|
8
|
-
const intervalId = setInterval(() => {
|
|
9
|
-
if (!timer.value) clearInterval(intervalId)
|
|
10
|
-
return timer.value--
|
|
11
|
-
}, 1000)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
onMounted(() => runTimer())
|
|
15
|
-
</script>
|
|
16
|
-
|
|
17
|
-
<template>
|
|
18
|
-
<section class="flex flex-col items-stretch gap-4 py-4 py-8 text-center md:px-8">
|
|
19
|
-
<h2 class="text-2xl font-bold">
|
|
20
|
-
{{ $t('register.modal.title') }}
|
|
21
|
-
</h2>
|
|
22
|
-
<span class="mx-auto">
|
|
23
|
-
<a-ill-mail/>
|
|
24
|
-
</span>
|
|
25
|
-
<p class="text-sm">
|
|
26
|
-
{{ $t('register.modal.subtitle1') }}
|
|
27
|
-
</p>
|
|
28
|
-
<p class="text-sm">
|
|
29
|
-
{{ $t('register.modal.subtitle2') }}
|
|
30
|
-
</p>
|
|
31
|
-
<div v-if="timer > 0" class="text-2xl font-bold">
|
|
32
|
-
{{ timer }} {{ $t('register.modal.seconds') }}
|
|
33
|
-
</div>
|
|
34
|
-
<button
|
|
35
|
-
v-else
|
|
36
|
-
class="text-sm text-blue-500"
|
|
37
|
-
@click="$emit('repeated')"
|
|
38
|
-
>
|
|
39
|
-
{{ $t('register.modal.resend') }}
|
|
40
|
-
</button>
|
|
41
|
-
<a-button @click="$emit('back')">
|
|
42
|
-
{{ $t('actions.back') }}
|
|
43
|
-
</a-button>
|
|
44
|
-
</section>
|
|
45
|
-
</template>
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
const { emailModal } = useIdModals()
|
|
3
|
-
const { t } = useI18n()
|
|
4
|
-
</script>
|
|
5
|
-
|
|
6
|
-
<template>
|
|
7
|
-
<a-modal v-model="emailModal">
|
|
8
|
-
<div class="flex flex-col items-stretch gap-5 rounded-lg text-center">
|
|
9
|
-
<h2 class="text-center text-2xl font-bold">
|
|
10
|
-
{{ t('modals.id.email.title') }}
|
|
11
|
-
</h2>
|
|
12
|
-
<div class="flex justify-center">
|
|
13
|
-
<span class="flex size-[100px] items-center justify-center rounded-full bg-[#BDC7CE26]">
|
|
14
|
-
<a-ill-info />
|
|
15
|
-
</span>
|
|
16
|
-
</div>
|
|
17
|
-
<p class="text-center text-sm">
|
|
18
|
-
{{ t('modals.id.email.content') }}
|
|
19
|
-
</p>
|
|
20
|
-
<a-button @click="emailModal = false">
|
|
21
|
-
{{ t('actions.close') }}
|
|
22
|
-
</a-button>
|
|
23
|
-
</div>
|
|
24
|
-
</a-modal>
|
|
25
|
-
</template>
|
|
26
|
-
|
|
27
|
-
<style scoped>
|
|
28
|
-
|
|
29
|
-
</style>
|