adata-ui 2.0.29 → 2.0.30

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.
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import OtpInput from '#adata-ui/components/modals/id/otp-input.vue'
2
+ import IdOtpInput from '#adata-ui/components/modals/id/IdOtpInput.vue'
3
3
  import { useAuthStore } from '#adata-ui/stores/auth.store'
4
4
 
5
5
  const { $toast } = useNuxtApp()
@@ -17,26 +17,42 @@ const otp = ref(['', '', '', '', '', ''])
17
17
  const otpFormatted = computed(() => {
18
18
  return otp.value.join('')
19
19
  })
20
- const attempts = ref(5)
21
20
  const showError = ref(false)
22
21
  const isLoading = ref(false)
23
22
 
24
- async function onResend() {
25
- try {
26
- await $fetch(`${authApiURL}/email/resend-otp`, {
27
- method: 'GET',
28
- credentials: 'include',
29
- headers: {
30
- lang: locale.value,
31
- },
32
- params: {
33
- email: intermediateState.value.email,
34
- },
35
- })
36
- runTimer()
37
- }
38
- catch (error) {
39
- $toast.error(error.data)
23
+ async function loginUser() {
24
+ const login = await fetch(`${authApiURL}/login`, {
25
+ method: 'POST',
26
+ credentials: 'include',
27
+ headers: {
28
+ 'Content-Type': 'application/json',
29
+ 'lang': locale.value,
30
+ },
31
+ body: JSON.stringify({
32
+ username: intermediateState.value.email,
33
+ password: intermediateState.value.password,
34
+ }),
35
+ })
36
+ await login.json().catch(() => ({}))
37
+
38
+ const response = await fetch(`${authApiURL}/access/cookie`, {
39
+ method: 'GET',
40
+ credentials: 'include',
41
+ headers: {
42
+ lang: locale.value,
43
+ },
44
+ })
45
+ const { data: cookiesData } = await response.json()
46
+ if (cookiesData) {
47
+ const { access_token, expire_in } = cookiesData
48
+ const hostname = location.hostname.split('.').reverse()
49
+
50
+ useCookie('accessToken', {
51
+ maxAge: expire_in,
52
+ domain: `.${hostname[1]}.${hostname[0]}`,
53
+ path: '/',
54
+ secure: true,
55
+ }).value = access_token
40
56
  }
41
57
  }
42
58
 
@@ -56,31 +72,49 @@ async function onConfirm() {
56
72
  },
57
73
  })
58
74
 
75
+ await loginUser()
76
+
59
77
  confirmAccountOtpModal.value = false
60
78
  confirmSuccessfulModal.value = true
61
79
  }
62
80
  catch (error) {
63
- if (error.data?.retry_after) {
64
- attempts.value = 0
65
- }
66
- else {
67
- attempts.value--
68
- }
69
81
  showError.value = true
70
- $toast.error(error.data.message)
71
82
  }
72
83
  finally {
73
84
  isLoading.value = false
74
85
  }
75
86
  }
76
87
 
77
- function onClose() {
88
+ function resetOtp() {
78
89
  otp.value = ['', '', '', '', '', '']
79
90
  showError.value = false
80
- attempts.value = 5
91
+ }
92
+
93
+ function onClose() {
94
+ resetOtp()
81
95
  confirmAccountOtpModal.value = false
82
96
  }
83
97
 
98
+ async function onResend() {
99
+ try {
100
+ await $fetch(`${authApiURL}/email/resend-otp`, {
101
+ method: 'GET',
102
+ credentials: 'include',
103
+ headers: {
104
+ lang: locale.value,
105
+ },
106
+ params: {
107
+ email: intermediateState.value.email,
108
+ },
109
+ })
110
+ resetOtp()
111
+ runTimer()
112
+ }
113
+ catch (error) {
114
+ $toast.error(error.data)
115
+ }
116
+ }
117
+
84
118
  const timer = ref(60)
85
119
 
86
120
  function runTimer() {
@@ -133,28 +167,18 @@ onBeforeUnmount(() => {
133
167
  </button>
134
168
  </div>
135
169
 
136
- <otp-input
170
+ <id-otp-input
137
171
  v-model="otp"
138
172
  v-model:error="showError"
139
- :attempts="attempts"
173
+ @on-completed="onConfirm"
140
174
  />
141
175
 
142
- <div class="flex w-full gap-2">
143
- <a-button
144
- block
145
- view="outline"
146
- @click="onClose"
147
- >
148
- {{ t('actions.close') }}
149
- </a-button>
150
- <a-button
151
- block
152
- :loading="isLoading"
153
- :disabled="otpFormatted.length < 6 || attempts === 0"
154
- @click="onConfirm"
155
- >
156
- {{ t('actions.confirm') }}
157
- </a-button>
158
- </div>
176
+ <a-button
177
+ block
178
+ view="outline"
179
+ @click="onClose"
180
+ >
181
+ {{ t('actions.close') }}
182
+ </a-button>
159
183
  </div>
160
184
  </template>
@@ -1,6 +1,11 @@
1
1
  <script setup lang="ts">
2
- const { confirmSuccessfulModal } = useIdModals()
3
2
  const { t } = useI18n()
3
+ const { confirmSuccessfulModal } = useIdModals()
4
+
5
+ function onClose() {
6
+ confirmSuccessfulModal.value = false
7
+ window.location.reload()
8
+ }
4
9
  </script>
5
10
 
6
11
  <template>
@@ -14,7 +19,7 @@ const { t } = useI18n()
14
19
  <p class="text-sm">
15
20
  {{ t('modals.id.confirmSuccessful.content') }}
16
21
  </p>
17
- <a-button view="outline" @click="confirmSuccessfulModal = false">
22
+ <a-button view="outline" @click="onClose">
18
23
  {{ t('actions.close') }}
19
24
  </a-button>
20
25
  </div>
@@ -36,7 +36,7 @@ const {
36
36
  <a-modal v-model="confirmAccountOtpModal" prevent-close>
37
37
  <id-confirm-account-otp-modal v-if="confirmAccountOtpModal" />
38
38
  </a-modal>
39
- <a-modal v-model="confirmSuccessfulModal">
39
+ <a-modal v-model="confirmSuccessfulModal" prevent-close>
40
40
  <id-confirm-successful-modal v-if="confirmSuccessfulModal" />
41
41
  </a-modal>
42
42
 
@@ -1,6 +1,6 @@
1
1
  <script lang="ts" setup>
2
- defineProps<{
3
- attempts?: number
2
+ const emit = defineEmits<{
3
+ (e: 'onCompleted', value: string): void
4
4
  }>()
5
5
 
6
6
  const length = 6 // Длина OTP
@@ -9,6 +9,12 @@ const otp = defineModel()
9
9
  const otpRefs = ref([])
10
10
  const { t } = useI18n()
11
11
 
12
+ function checkCompletion() {
13
+ if (otp.value.every(val => val !== '')) {
14
+ emit('onCompleted', otp.value.join(''))
15
+ }
16
+ }
17
+
12
18
  function onInput(event, index) {
13
19
  const value = event.target.value
14
20
  showError.value = false
@@ -20,6 +26,7 @@ function onInput(event, index) {
20
26
  }
21
27
 
22
28
  otp.value[index] = value
29
+ checkCompletion()
23
30
 
24
31
  // Перемещаем фокус на следующий элемент, если введен символ
25
32
  if (value && index < length - 1) {
@@ -63,6 +70,7 @@ function onPaste(event) {
63
70
  otp.value[index] = char
64
71
  }
65
72
  })
73
+ checkCompletion()
66
74
 
67
75
  // Ставим фокус на следующий незаполненный элемент
68
76
  const firstEmptyIndex = otp.value.findIndex(val => val === '')
@@ -117,8 +125,8 @@ function moveFocus(index: number, to: string) {
117
125
  v-model="otp[index]"
118
126
  type="text"
119
127
  maxlength="1"
120
- class="bg-deepblue-900/5 dark:bg-[#E3E5E80D] size-10 rounded text-center text-lg focus:border-blue-500 focus:outline-none focus:border caret-transparent"
121
- :class="{ 'border border-[#E74135] dark:border-[#F47E75] dark:bg-[#F47E751A] bg-[#E741351A]': showError }"
128
+ class="size-10 rounded bg-deepblue-900/5 text-center text-lg caret-transparent focus:border focus:border-blue-500 focus:outline-none dark:bg-[#E3E5E80D]"
129
+ :class="{ 'border border-[#E74135] bg-[#E741351A] dark:border-[#F47E75] dark:bg-[#F47E751A]': showError }"
122
130
  @input="onInput($event, index)"
123
131
  @keydown.backspace="onBackspace(index, $event)"
124
132
  @keydown.enter.prevent
@@ -137,10 +145,6 @@ function moveFocus(index: number, to: string) {
137
145
  >
138
146
  {{ t('error.otp') }}
139
147
  </a-alert>
140
-
141
- <p v-show="showError" class="mt-1 text-xs text-red-500 dark:text-red-400">
142
- {{ t('modals.id.resetPasswordOtp.attempts', { n: attempts }) }}
143
- </p>
144
148
  </div>
145
149
  </template>
146
150
 
@@ -84,9 +84,10 @@ async function onSubmit() {
84
84
  })
85
85
  if (success) {
86
86
  intermediateState.value.email = form.email
87
+ intermediateState.value.password = form.password
88
+
87
89
  registrationModal.value = false
88
90
  confirmAccountOtpModal.value = true
89
- $toast.success(message)
90
91
  }
91
92
  }
92
93
  catch (error) {
@@ -117,7 +118,7 @@ function getUrl() {
117
118
  }
118
119
 
119
120
  function handleEnter(event: KeyboardEvent) {
120
- if (event.key === 'Enter' && !confirmAccountOtpModal.value) {
121
+ if (event.key === 'Enter') {
121
122
  onSubmit()
122
123
  }
123
124
  }
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import OtpInput from '#adata-ui/components/modals/id/otp-input.vue'
2
+ import IdOtpInput from '#adata-ui/components/modals/id/IdOtpInput.vue'
3
3
  import { useAuthStore } from '#adata-ui/stores/auth.store'
4
4
 
5
5
  const { $toast } = useNuxtApp()
@@ -17,7 +17,6 @@ const otp = ref(['', '', '', '', '', ''])
17
17
  const otpFormatted = computed(() => {
18
18
  return otp.value.join('')
19
19
  })
20
- const attempts = ref(5)
21
20
  const showError = ref(false)
22
21
  const isLoading = ref(false)
23
22
 
@@ -44,20 +43,23 @@ async function onConfirm() {
44
43
  newPasswordModal.value = true
45
44
  }
46
45
  catch (error) {
47
- if (error.data?.retry_after) {
48
- attempts.value = 0
49
- }
50
- else {
51
- attempts.value--
52
- }
53
46
  showError.value = true
54
- $toast.error(error.data.message)
55
47
  }
56
48
  finally {
57
49
  isLoading.value = false
58
50
  }
59
51
  }
60
52
 
53
+ function resetOtp() {
54
+ otp.value = ['', '', '', '', '', '']
55
+ showError.value = false
56
+ }
57
+
58
+ function onClose() {
59
+ resetOtp()
60
+ resetPasswordOtpModal.value = false
61
+ }
62
+
61
63
  async function onResend() {
62
64
  try {
63
65
  await $fetch(`${authApiURL}/password/email-otp`, {
@@ -70,6 +72,7 @@ async function onResend() {
70
72
  email: intermediateState.value.email,
71
73
  },
72
74
  })
75
+ resetOtp()
73
76
  runTimer()
74
77
  }
75
78
  catch (error) {
@@ -77,13 +80,6 @@ async function onResend() {
77
80
  }
78
81
  }
79
82
 
80
- function onClose() {
81
- otp.value = ['', '', '', '', '', '']
82
- attempts.value = 5
83
- showError.value = false
84
- resetPasswordOtpModal.value = false
85
- }
86
-
87
83
  function handleEnter(e: KeyboardEvent) {
88
84
  if (e.key === 'Enter') {
89
85
  onConfirm()
@@ -136,29 +132,19 @@ onBeforeUnmount(() => {
136
132
  </button>
137
133
  </div>
138
134
 
139
- <otp-input
135
+ <id-otp-input
140
136
  v-model="otp"
141
137
  v-model:error="showError"
142
- :attempts="attempts"
138
+ @on-completed="onConfirm"
143
139
  />
144
140
 
145
- <div class="flex w-full gap-2">
146
- <a-button
147
- block
148
- view="outline"
149
- @click="onClose"
150
- >
151
- {{ t('actions.close') }}
152
- </a-button>
153
- <a-button
154
- block
155
- :loading="isLoading"
156
- :disabled="otpFormatted.length < 6 || attempts === 0"
157
- @click="onConfirm"
158
- >
159
- {{ t('actions.confirm') }}
160
- </a-button>
161
- </div>
141
+ <a-button
142
+ block
143
+ view="outline"
144
+ @click="onClose"
145
+ >
146
+ {{ t('actions.close') }}
147
+ </a-button>
162
148
  </div>
163
149
  </template>
164
150
 
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import OtpInput from '#adata-ui/components/modals/id/otp-input.vue'
2
+ import IdOtpInput from '#adata-ui/components/modals/id/IdOtpInput.vue'
3
3
  import { useAuthStore } from '#adata-ui/stores/auth.store'
4
4
 
5
5
  const { $toast } = useNuxtApp()
@@ -98,27 +98,22 @@ onBeforeUnmount(() => {
98
98
  </p>
99
99
  <a-icon-hand-with-phone-light class="size-32 dark:hidden" />
100
100
  <a-icon-hand-with-phone-dark class="hidden size-32 dark:block" />
101
- <otp-input v-model="otp" v-model:error="showError" />
101
+ <id-otp-input
102
+ v-model="otp"
103
+ v-model:error="showError"
104
+ @on-completed="onConfirm"
105
+ />
102
106
  <p class="body-400 text-center">
103
107
  {{ t('modals.id.twoFactor.code') }}
104
108
  </p>
105
- <div class="flex w-full gap-2">
106
- <a-button
107
- class="w-full"
108
- view="outline"
109
- @click="onClose"
110
- >
111
- {{ t('actions.close') }}
112
- </a-button>
113
- <a-button
114
- :loading="isLoading"
115
- :disabled="otpFormatted.length < 6"
116
- class="w-full"
117
- @click="onConfirm"
118
- >
119
- {{ t('actions.confirm') }}
120
- </a-button>
121
- </div>
109
+
110
+ <a-button
111
+ class="w-full"
112
+ view="outline"
113
+ @click="onClose"
114
+ >
115
+ {{ t('actions.close') }}
116
+ </a-button>
122
117
  </div>
123
118
  </template>
124
119
 
package/lang/en.ts CHANGED
@@ -520,7 +520,7 @@ const EnLocale: RuLocale = {
520
520
  resetPasswordOtp: {
521
521
  title: 'Confirm action',
522
522
  content: 'Enter the 6-digit confirmation code sent to your email address',
523
- seconds: 'Seconds',
523
+ seconds: 'seconds',
524
524
  attempts: 'Remaining attempts: {n}',
525
525
  },
526
526
  newPassword: {
package/lang/kk.ts CHANGED
@@ -521,7 +521,7 @@ const KkLocale: RuLocale = {
521
521
  resetPasswordOtp: {
522
522
  title: 'Әрекетті растау',
523
523
  content: 'Электрондық поштаға жіберілген 6 таңбалы кодты енгізіңіз',
524
- seconds: 'Секунд',
524
+ seconds: 'секунд',
525
525
  attempts: 'Қалған әрекет саны: {n}',
526
526
  },
527
527
  newPassword: {
package/lang/ru.ts CHANGED
@@ -522,7 +522,7 @@ const RuLocale = {
522
522
  resetPasswordOtp: {
523
523
  title: 'Подтвердите действие',
524
524
  content: 'Введите 6-значный код подтверждения отправленный на ваш адрес электронной почты',
525
- seconds: 'Секунд',
525
+ seconds: 'секунд',
526
526
  attempts: 'Повторных попыток осталось: {n}',
527
527
  },
528
528
  newPassword: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "adata-ui",
3
3
  "type": "module",
4
- "version": "2.0.29",
4
+ "version": "2.0.30",
5
5
  "main": "./nuxt.config.ts",
6
6
  "scripts": {
7
7
  "dev": "nuxi dev .playground",