adata-ui 2.0.24 → 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.
@@ -0,0 +1,147 @@
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 { confirmAccountOtpModal, confirmSuccessfulModal } = 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 onResend() {
24
+ try {
25
+ await $fetch(`${authApiURL}/email/resend-otp`, {
26
+ method: 'GET',
27
+ credentials: 'include',
28
+ headers: {
29
+ lang: locale.value,
30
+ },
31
+ body: {
32
+ email: intermediateState.value.email,
33
+ },
34
+ })
35
+ runTimer()
36
+ }
37
+ catch (error) {
38
+ $toast.error(error.data)
39
+ }
40
+ }
41
+
42
+ async function onConfirm() {
43
+ try {
44
+ isLoading.value = true
45
+
46
+ await $fetch(`${authApiURL}/email/verify-otp`, {
47
+ method: 'GET',
48
+ credentials: 'include',
49
+ headers: {
50
+ lang: locale.value,
51
+ },
52
+ params: {
53
+ email: intermediateState.value.email,
54
+ otp_code: otpFormatted.value,
55
+ },
56
+ })
57
+
58
+ confirmAccountOtpModal.value = false
59
+ confirmSuccessfulModal.value = true
60
+ }
61
+ catch (error) {
62
+ showError.value = true
63
+ $toast.error(error.data.message)
64
+ }
65
+ finally {
66
+ isLoading.value = false
67
+ }
68
+ }
69
+
70
+ function onClose() {
71
+ otp.value = ['', '', '', '', '', '']
72
+ showError.value = false
73
+ confirmAccountOtpModal.value = false
74
+ }
75
+
76
+ const timer = ref(60)
77
+
78
+ function runTimer() {
79
+ const intervalId = setInterval(() => {
80
+ if (!timer.value) clearInterval(intervalId)
81
+ return timer.value--
82
+ }, 1000)
83
+ }
84
+
85
+ function handleEnter(e: KeyboardEvent) {
86
+ if (e.key === 'Enter') {
87
+ onConfirm()
88
+ }
89
+ }
90
+
91
+ onMounted(() => {
92
+ runTimer()
93
+ document.addEventListener('keyup', handleEnter)
94
+ })
95
+
96
+ onBeforeUnmount(() => {
97
+ document.removeEventListener('keyup', handleEnter)
98
+ })
99
+ </script>
100
+
101
+ <template>
102
+ <div class="flex flex-col items-center gap-4 text-center">
103
+ <h2 class="text-2xl font-bold">
104
+ {{ t('register.modal.title') }}
105
+ </h2>
106
+
107
+ <a-icon-hand-with-phone-light class="size-32 dark:hidden" />
108
+ <a-icon-hand-with-phone-dark class="hidden size-32 dark:block" />
109
+
110
+ <div class="text-sm">
111
+ <p class="mb-1">
112
+ {{ t('modals.id.resetPasswordOtp.content') }}
113
+ </p>
114
+
115
+ <div v-if="timer > 0" class="text-2xl font-bold">
116
+ {{ timer }} {{ t('register.modal.seconds') }}
117
+ </div>
118
+ <button
119
+ v-else
120
+ class="text-blue-700 dark:text-blue-500"
121
+ @click="onResend"
122
+ >
123
+ {{ t('actions.resend') }}
124
+ </button>
125
+ </div>
126
+
127
+ <otp-input v-model="otp" v-model:error="showError" />
128
+
129
+ <div class="flex w-full gap-2">
130
+ <a-button
131
+ block
132
+ view="outline"
133
+ @click="onClose"
134
+ >
135
+ {{ t('actions.close') }}
136
+ </a-button>
137
+ <a-button
138
+ block
139
+ :loading="isLoading"
140
+ :disabled="otpFormatted.length < 6"
141
+ @click="onConfirm"
142
+ >
143
+ {{ t('actions.confirm') }}
144
+ </a-button>
145
+ </div>
146
+ </div>
147
+ </template>
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ const { confirmSuccessfulModal } = useIdModals()
3
+ const { t } = useI18n()
4
+ </script>
5
+
6
+ <template>
7
+ <div class="flex flex-col gap-4 text-center">
8
+ <h2 class="text-2xl font-bold">
9
+ {{ t('modals.id.confirmSuccessful.title') }}
10
+ </h2>
11
+ <span class="mx-auto size-[100px] rounded-full bg-[#BDC7CE26]">
12
+ <a-ill-ok />
13
+ </span>
14
+ <p class="text-sm">
15
+ {{ t('modals.id.confirmSuccessful.content') }}
16
+ </p>
17
+ <a-button view="outline" @click="confirmSuccessfulModal = false">
18
+ {{ t('actions.close') }}
19
+ </a-button>
20
+ </div>
21
+ </template>
22
+
23
+ <style scoped>
24
+
25
+ </style>
@@ -1,7 +1,6 @@
1
1
  <script setup lang="ts">
2
- import AConfirmationEmail from '#adata-ui/components/modals/AConfirmationEmail.vue'
3
- import Resend from '#adata-ui/components/modals/Resend.vue'
4
2
  import TwoFactor from '#adata-ui/components/modals/two-factor/two-factor.vue'
3
+ import { useAuthStore } from '#adata-ui/stores/auth.store'
5
4
  import { navigateToLocalizedPage } from '#adata-ui/utils/localizedNavigation'
6
5
  import { useToggle } from '@vueuse/shared'
7
6
  import * as z from 'zod'
@@ -13,13 +12,14 @@ const isConfirmationEmailModal = ref(false)
13
12
  const isTwoFactorOpen = ref(false)
14
13
  const isLoadingOtp = ref(false)
15
14
  const { $api, $toast } = useNuxtApp()
16
- const localePath = useLocalePath()
17
15
  const showOtpError = ref(false)
18
16
  const { t, locale } = useI18n()
19
- const route = useRoute()
20
17
  const submitted = ref(false)
21
18
  const accessToken = ref(null)
22
- const { loginModal, registrationModal, recoveryModal } = useIdModals()
19
+ const { loginModal, registrationModal, recoveryModal, confirmAccountOtpModal } = useIdModals()
20
+
21
+ const authStore = useAuthStore()
22
+ const { intermediateState } = storeToRefs(authStore)
23
23
 
24
24
  export interface ILoginForm {
25
25
  username: string
@@ -84,7 +84,22 @@ async function submit() {
84
84
  $toast.error(t('error.validation'))
85
85
  }
86
86
  else {
87
- $toast.error(message)
87
+ intermediateState.value.email = form.username
88
+ intermediateState.value.password = form.password
89
+
90
+ await fetch(`${authApiURL}/email/resend-otp`, {
91
+ method: 'GET',
92
+ credentials: 'include',
93
+ headers: {
94
+ 'Content-Type': 'application/json',
95
+ 'lang': locale.value,
96
+ },
97
+ body: JSON.stringify({
98
+ email: intermediateState.value.email,
99
+ }),
100
+ }).catch(() => {})
101
+
102
+ confirmAccountOtpModal.value = true
88
103
  }
89
104
  }
90
105
  else {
@@ -112,7 +127,20 @@ async function submit() {
112
127
  window.location.reload()
113
128
  }
114
129
  else {
115
- isConfirmationEmailModal.value = true
130
+ intermediateState.value.email = form.username
131
+ intermediateState.value.password = form.password
132
+ confirmAccountOtpModal.value = true
133
+
134
+ $fetch(`${authApiURL}/email/resend-otp`, {
135
+ method: 'GET',
136
+ credentials: 'include',
137
+ headers: {
138
+ lang: locale.value,
139
+ },
140
+ body: {
141
+ email: intermediateState.value.email,
142
+ },
143
+ }).catch(() => {})
116
144
  }
117
145
  }
118
146
  loading.value = false
@@ -165,8 +193,8 @@ async function handleConfirmOtp(otpCode: string) {
165
193
  'lang': locale.value,
166
194
  },
167
195
  body: JSON.stringify({
168
- 'username': form.username.trim(),
169
- 'password': form.password.toString(),
196
+ 'username': intermediateState.value.email.trim(),
197
+ 'password': intermediateState.value.password.toString(),
170
198
  '2fa_code': otpCode,
171
199
  }),
172
200
  })
@@ -195,6 +223,7 @@ async function handleConfirmOtp(otpCode: string) {
195
223
  }
196
224
  $toast.success(t('login.successfully'))
197
225
  loginModal.value = false
226
+ window.location.reload()
198
227
 
199
228
  isTwoFactorOpen.value = false
200
229
  }
@@ -217,14 +246,6 @@ function onForgotPassword() {
217
246
  recoveryModal.value = true
218
247
  }
219
248
 
220
- watch(loginModal, (value) => {
221
- if (!value) {
222
- form.username = ''
223
- form.password = ''
224
- rememberMe.value = false
225
- }
226
- })
227
-
228
249
  onMounted(() => {
229
250
  document.addEventListener('keyup', handleEnter)
230
251
  })
@@ -235,124 +256,122 @@ onBeforeUnmount(() => {
235
256
  </script>
236
257
 
237
258
  <template>
238
- <a-modal v-model="loginModal">
239
- <div class="flex flex-col gap-5">
240
- <h1 class="heading-02 text-center">
241
- {{ $t('login.form.title') }}
242
- </h1>
243
- <p class="body-400 text-center">
244
- {{ $t('login.form.subtitle') }}
245
- </p>
246
- <div class="flex flex-col gap-4">
247
- <a-input-standard
248
- v-model="form.username"
249
- type="email"
250
- :label="$t('login.form.labels.email')"
251
- :error="getError('username')"
252
- />
253
- <a-input-password
254
- v-model="form.password"
255
- :label="$t('login.form.labels.password')"
256
- :error="getError('password')"
257
- />
258
- <div class="flex items-center justify-between">
259
- <div class="body-400 flex gap-2">
260
- <a-checkbox
261
- v-model="rememberMe"
262
- name="remember_me"
263
- />
264
- <label
265
- for="remember_me"
266
- class="cursor-pointer"
267
- >{{
268
- $t('login.form.remember_me')
269
- }}</label>
270
- </div>
271
- <button
272
- class="link-s-400"
273
- @click="onForgotPassword"
274
- >
275
- {{ $t('login.form.forget_password') }}
276
- </button>
277
- </div>
278
- </div>
279
- <div class="flex items-center gap-4">
280
- <div class="h-px w-full bg-deepblue-500/30" />
281
- <div class="flex shrink-0 gap-4">
282
- <span
283
- class="cursor-pointer"
284
- @click="authWithSocial('google')"
285
- >
286
- <a-icon-google />
287
- </span>
288
- <span
289
- class="cursor-pointer"
290
- @click="authWithSocial('yandex')"
291
- >
292
- <a-icon-yandex />
293
- </span>
294
- <span
259
+ <div class="flex flex-col gap-5">
260
+ <h1 class="heading-02 text-center">
261
+ {{ $t('login.form.title') }}
262
+ </h1>
263
+ <p class="body-400 text-center">
264
+ {{ $t('login.form.subtitle') }}
265
+ </p>
266
+ <div class="flex flex-col gap-4">
267
+ <a-input-standard
268
+ v-model="form.username"
269
+ type="email"
270
+ :label="$t('login.form.labels.email')"
271
+ :error="getError('username')"
272
+ />
273
+ <a-input-password
274
+ v-model="form.password"
275
+ :label="$t('login.form.labels.password')"
276
+ :error="getError('password')"
277
+ />
278
+ <div class="flex items-center justify-between">
279
+ <div class="body-400 flex gap-2">
280
+ <a-checkbox
281
+ v-model="rememberMe"
282
+ name="remember_me"
283
+ />
284
+ <label
285
+ for="remember_me"
295
286
  class="cursor-pointer"
296
- @click="authWithSocial('mailru')"
297
- >
298
- <a-icon-mailru />
299
- </span>
287
+ >{{
288
+ $t('login.form.remember_me')
289
+ }}</label>
300
290
  </div>
301
- <div class="h-px w-full bg-deepblue-500/30" />
291
+ <button
292
+ class="link-s-400"
293
+ @click="onForgotPassword"
294
+ >
295
+ {{ $t('login.form.forget_password') }}
296
+ </button>
302
297
  </div>
303
- <a-button
304
- :loading="loading"
305
- type="submit"
306
- @click="submit"
307
- >
308
- {{ $t('actions.login') }}
309
- </a-button>
310
- <p class="body-400 text-center">
311
- {{ $t('login.form.first_time') }}
312
- </p>
313
-
314
- <a-button
315
- type="button"
316
- view="outline"
317
- class="w-full"
318
- @click="onRegister"
319
- >
320
- {{ $t('actions.register') }}
321
- </a-button>
322
-
323
- <a-button
324
- type="button"
325
- view="transparent"
326
- class="w-full"
327
- @click="toTariffs"
328
- >
329
- {{ $t('actions.toTariffs') }}
330
- </a-button>
331
-
332
- <a-alert
333
- class="max-w-screen-sm !text-[10px]"
334
- size="xs"
335
- >
336
- {{ $t('info.userAgreement') }}
337
- </a-alert>
338
298
  </div>
339
- </a-modal>
340
-
341
- <a-modal v-model="isResendModal">
342
- <resend
343
- v-if="isResendModal"
344
- @close="isResendModal = false"
345
- @resend="onResend"
346
- />
347
- </a-modal>
348
-
349
- <a-modal v-model="isConfirmationEmailModal">
350
- <a-confirmation-email
351
- v-if="isConfirmationEmailModal"
352
- @close="isConfirmationEmailModal = false"
353
- @resend="confirmationEmailResend"
354
- />
355
- </a-modal>
299
+ <div class="flex items-center gap-4">
300
+ <div class="h-px w-full bg-deepblue-500/30" />
301
+ <div class="flex shrink-0 gap-4">
302
+ <span
303
+ class="cursor-pointer"
304
+ @click="authWithSocial('google')"
305
+ >
306
+ <a-icon-google />
307
+ </span>
308
+ <span
309
+ class="cursor-pointer"
310
+ @click="authWithSocial('yandex')"
311
+ >
312
+ <a-icon-yandex />
313
+ </span>
314
+ <span
315
+ class="cursor-pointer"
316
+ @click="authWithSocial('mailru')"
317
+ >
318
+ <a-icon-mailru />
319
+ </span>
320
+ </div>
321
+ <div class="h-px w-full bg-deepblue-500/30" />
322
+ </div>
323
+ <a-button
324
+ :loading="loading"
325
+ type="submit"
326
+ @click="submit"
327
+ >
328
+ {{ $t('actions.login') }}
329
+ </a-button>
330
+ <p class="body-400 text-center">
331
+ {{ $t('login.form.first_time') }}
332
+ </p>
333
+
334
+ <a-button
335
+ type="button"
336
+ view="outline"
337
+ class="w-full"
338
+ @click="onRegister"
339
+ >
340
+ {{ $t('actions.register') }}
341
+ </a-button>
342
+
343
+ <a-button
344
+ type="button"
345
+ view="transparent"
346
+ class="w-full"
347
+ @click="toTariffs"
348
+ >
349
+ {{ $t('actions.toTariffs') }}
350
+ </a-button>
351
+
352
+ <a-alert
353
+ class="max-w-screen-sm !text-[10px]"
354
+ size="xs"
355
+ >
356
+ {{ $t('info.userAgreement') }}
357
+ </a-alert>
358
+ </div>
359
+
360
+ <!-- <a-modal v-model="isResendModal"> -->
361
+ <!-- <resend -->
362
+ <!-- v-if="isResendModal" -->
363
+ <!-- @close="isResendModal = false" -->
364
+ <!-- @resend="onResend" -->
365
+ <!-- /> -->
366
+ <!-- </a-modal> -->
367
+
368
+ <!-- <a-modal v-model="isConfirmationEmailModal"> -->
369
+ <!-- <a-confirmation-email -->
370
+ <!-- v-if="isConfirmationEmailModal" -->
371
+ <!-- @close="isConfirmationEmailModal = false" -->
372
+ <!-- @resend="confirmationEmailResend" -->
373
+ <!-- /> -->
374
+ <!-- </a-modal> -->
356
375
 
357
376
  <two-factor
358
377
  v-model="isTwoFactorOpen"
@@ -1,19 +1,53 @@
1
1
  <script setup lang="ts">
2
- import IdEmailModal from '#adata-ui/components/modals/id/IdEmailModal.vue'
2
+ import IdConfirmAccountOtpModal from '#adata-ui/components/modals/id/IdConfirmAccountOtpModal.vue'
3
+ import IdConfirmSuccessfulModal from '#adata-ui/components/modals/id/IdConfirmSuccessfulModal.vue'
3
4
  import IdLoginModal from '#adata-ui/components/modals/id/IdLoginModal.vue'
4
5
  import IdNewPasswordModal from '#adata-ui/components/modals/id/IdNewPasswordModal.vue'
5
6
  import IdPasswordSuccessfulModal from '#adata-ui/components/modals/id/IdPasswordSuccessfulModal.vue'
6
7
  import IdRecoveryModal from '#adata-ui/components/modals/id/IdRecoveryModal.vue'
7
8
  import IdRegistrationModal from '#adata-ui/components/modals/id/IdRegistrationModal.vue'
9
+ import IdResetPasswordOtpModal from '#adata-ui/components/modals/id/IdResetPasswordOtpModal.vue'
10
+
11
+ const {
12
+ loginModal,
13
+ registrationModal,
14
+ confirmAccountOtpModal,
15
+ recoveryModal,
16
+ resetPasswordOtpModal,
17
+ newPasswordModal,
18
+ passwordSuccessfulModal,
19
+ confirmSuccessfulModal,
20
+ twoFactorModal,
21
+ } = useIdModals()
8
22
  </script>
9
23
 
10
24
  <template>
11
- <id-login-modal />
12
- <id-registration-modal />
13
- <id-recovery-modal />
14
- <id-email-modal />
15
- <id-new-password-modal />
16
- <id-password-successful-modal />
25
+ <a-modal v-model="loginModal">
26
+ <id-login-modal />
27
+ </a-modal>
28
+
29
+ <a-modal v-model="registrationModal">
30
+ <id-registration-modal v-if="registrationModal" />
31
+ </a-modal>
32
+ <a-modal v-model="confirmAccountOtpModal">
33
+ <id-confirm-account-otp-modal v-if="confirmAccountOtpModal" />
34
+ </a-modal>
35
+ <a-modal v-model="confirmSuccessfulModal">
36
+ <id-confirm-successful-modal v-if="confirmSuccessfulModal" />
37
+ </a-modal>
38
+
39
+ <a-modal v-model="recoveryModal">
40
+ <id-recovery-modal v-if="recoveryModal" />
41
+ </a-modal>
42
+ <a-modal v-model="resetPasswordOtpModal">
43
+ <id-reset-password-otp-modal v-if="resetPasswordOtpModal" />
44
+ </a-modal>
45
+ <a-modal v-model="newPasswordModal">
46
+ <id-new-password-modal v-if="newPasswordModal" />
47
+ </a-modal>
48
+ <a-modal v-model="passwordSuccessfulModal">
49
+ <id-password-successful-modal v-if="passwordSuccessfulModal" />
50
+ </a-modal>
17
51
  </template>
18
52
 
19
53
  <style scoped></style>