adata-ui 2.0.24 → 2.0.26

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 (35) hide show
  1. package/.nuxtrc +1 -1
  2. package/.playground/app.config.ts +5 -5
  3. package/README.md +75 -75
  4. package/components/elements/README.md +1 -1
  5. package/components/forms/README.md +1 -1
  6. package/components/modals/AConfirmationEmail.vue +40 -40
  7. package/components/modals/ContentNavigationModal.vue +38 -32
  8. package/components/modals/Resend.vue +81 -81
  9. package/components/modals/id/IdConfirmAccountOtpModal.vue +147 -0
  10. package/components/modals/id/IdConfirmSuccessfulModal.vue +25 -0
  11. package/components/modals/id/IdLoginModal.vue +150 -131
  12. package/components/modals/id/IdModals.vue +41 -7
  13. package/components/modals/id/IdNewPasswordModal.vue +55 -62
  14. package/components/modals/id/IdPasswordSuccessfulModal.vue +15 -16
  15. package/components/modals/id/IdRecoveryModal.vue +39 -34
  16. package/components/modals/id/IdRegistrationModal.vue +75 -103
  17. package/components/modals/id/IdResetPasswordOtpModal.vue +154 -0
  18. package/components/modals/two-factor/otp-input.vue +1 -1
  19. package/components/navigation/README.md +1 -1
  20. package/components/overlays/README.md +1 -1
  21. package/composables/useIdModals.ts +10 -2
  22. package/icons/chart-pie.vue +16 -0
  23. package/icons/google.vue +41 -41
  24. package/icons/linkedin.vue +24 -24
  25. package/icons/mailru.vue +34 -34
  26. package/icons/sun.vue +14 -14
  27. package/icons/work-case.vue +9 -0
  28. package/icons/yandex.vue +28 -28
  29. package/lang/ru.ts +16 -5
  30. package/layouts/default.vue +13 -13
  31. package/nuxt.config.ts +1 -0
  32. package/package.json +3 -1
  33. package/stores/auth.store.ts +12 -0
  34. package/components/modals/Accept.vue +0 -45
  35. package/components/modals/id/IdEmailModal.vue +0 -29
@@ -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>
@@ -1,14 +1,16 @@
1
1
  <script setup lang="ts">
2
+ import { useAuthStore } from '#adata-ui/stores/auth.store'
2
3
  import * as z from 'zod'
3
4
 
4
5
  const { $toast } = useNuxtApp()
5
6
  const { commonAuth } = useAppConfig()
6
- const route = useRoute()
7
7
  const { t, locale } = useI18n()
8
8
 
9
- const { email, token } = route.query
9
+ const authStore = useAuthStore()
10
+ const { intermediateState } = storeToRefs(authStore)
11
+
10
12
  const authApiURL = commonAuth.authApiURL
11
- const { loginModal, newPasswordModal, passwordSuccessfulModal } = useIdModals()
13
+ const { newPasswordModal, passwordSuccessfulModal } = useIdModals()
12
14
 
13
15
  const form = reactive({
14
16
  password: '',
@@ -51,22 +53,22 @@ async function onSubmit() {
51
53
  if (validation.value) return
52
54
  loading.value = true
53
55
 
54
- const { data } = await $fetch(`${authApiURL}/password/reset`, {
56
+ const response = await $fetch(`${authApiURL}/password/reset-otp`, {
55
57
  method: 'POST',
56
58
  credentials: 'include',
57
59
  headers: {
58
60
  lang: locale.value,
59
61
  },
60
62
  body: {
61
- token,
62
- email,
63
+ token: intermediateState.value.token,
64
+ email: intermediateState.value.email,
63
65
  ...form,
64
66
  },
65
67
  })
66
- if (data?.success) {
68
+ if (response?.success) {
67
69
  newPasswordModal.value = false
68
70
  passwordSuccessfulModal.value = true
69
- $toast.success(data.message)
71
+ $toast.success(response.message)
70
72
  }
71
73
  }
72
74
  catch (error) {
@@ -76,62 +78,53 @@ async function onSubmit() {
76
78
  loading.value = false
77
79
  }
78
80
  }
79
-
80
- // onMounted(() => {
81
- // if (!email || !token) {
82
- // newPasswordModal.value = false
83
- // loginModal.value = true
84
- // }
85
- // })
86
81
  </script>
87
82
 
88
83
  <template>
89
- <a-modal v-model="newPasswordModal">
90
- <form
91
- class="flex flex-col items-stretch gap-5"
92
- novalidate
93
- @submit.prevent="onSubmit"
84
+ <form
85
+ class="flex flex-col items-stretch gap-5"
86
+ novalidate
87
+ @submit.prevent="onSubmit"
88
+ >
89
+ <h2 class="text-center text-2xl font-bold">
90
+ {{ t('modals.id.newPassword.title') }}
91
+ </h2>
92
+ <p class="text-center text-sm">
93
+ {{ t('modals.id.newPassword.content') }}
94
+ </p>
95
+
96
+ <a-input-password
97
+ v-model="form.password"
98
+ :label="t('modals.id.newPassword.placeholder.1')"
99
+ :error="getError('password')"
100
+ />
101
+
102
+ <a-alert color="blue">
103
+ {{ t('modals.id.newPassword.alert') }}
104
+ </a-alert>
105
+
106
+ <a-input-password
107
+ v-model="form.password_confirmation"
108
+ :label="t('modals.id.newPassword.placeholder.2')"
109
+ :error="getError('password_confirmation')"
110
+ />
111
+
112
+ <a-button
113
+ :loading="loading"
114
+ >
115
+ {{ t('actions.set') }}
116
+ </a-button>
117
+
118
+ <p class="text-center text-sm">
119
+ {{ t('reuse.or') }}
120
+ </p>
121
+
122
+ <a-button
123
+ type="button"
124
+ view="outline"
125
+ @click="newPasswordModal = false"
94
126
  >
95
- <h2 class="text-center text-2xl font-bold">
96
- {{ t('resetPassword.title') }}
97
- </h2>
98
- <p class="text-center text-sm">
99
- {{ t('resetPassword.subtitle') }}
100
- </p>
101
-
102
- <a-input-password
103
- v-model="form.password"
104
- :label="t('register.form.labels.password')"
105
- :error="getError('password')"
106
- />
107
-
108
- <a-alert color="blue">
109
- {{ t('register.form.alert') }}
110
- </a-alert>
111
-
112
- <a-input-password
113
- v-model="form.password_confirmation"
114
- :label="t('register.form.labels.password_confirmation')"
115
- :error="getError('password_confirmation')"
116
- />
117
-
118
- <a-button
119
- :loading="loading"
120
- >
121
- {{ t('passwordRecovery.form.recover') }}
122
- </a-button>
123
-
124
- <p class="text-center text-sm">
125
- {{ t('passwordRecovery.form.or') }}
126
- </p>
127
-
128
- <a-button
129
- type="button"
130
- view="outline"
131
- @click="newPasswordModal = false"
132
- >
133
- {{ t('actions.cancel') }}
134
- </a-button>
135
- </form>
136
- </a-modal>
127
+ {{ t('actions.cancel') }}
128
+ </a-button>
129
+ </form>
137
130
  </template>
@@ -1,24 +1,23 @@
1
1
  <script setup lang="ts">
2
2
  const { passwordSuccessfulModal } = useIdModals()
3
+ const { t } = useI18n()
3
4
  </script>
4
5
 
5
6
  <template>
6
- <a-modal v-model="passwordSuccessfulModal">
7
- <section class="flex flex-col items-stretch gap-4 text-center">
8
- <h2 class="text-2xl font-bold">
9
- {{ $t('resetPassword.successModal.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('resetPassword.successModal.subtitle') }}
16
- </p>
17
- <a-button @click="passwordSuccessfulModal = false">
18
- {{ $t('resetPassword.successModal.goToAuthorization') }}
19
- </a-button>
20
- </section>
21
- </a-modal>
7
+ <div class="flex flex-col gap-4 text-center">
8
+ <h2 class="text-2xl font-bold">
9
+ {{ t('modals.id.passwordSuccessful.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.passwordSuccessful.content') }}
16
+ </p>
17
+ <a-button @click="passwordSuccessfulModal = false">
18
+ {{ t('actions.close') }}
19
+ </a-button>
20
+ </div>
22
21
  </template>
23
22
 
24
23
  <style scoped>