itube-specs 0.0.439 → 0.0.440

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,83 +1,90 @@
1
1
  <template>
2
- <div
3
- class="s-auth-register"
4
- :class="{'_loading': loading}"
5
- >
6
- <SIcon
7
- class="s-auth-register__icon"
8
- name="user-circle"
9
- size="40"
10
- />
11
- <p
12
- v-if="additionalText"
13
- class="s-auth-register__text"
14
- >{{ t(additionalText) }}</p>
15
- <SInput
16
- v-model="form.username"
17
- :label="t('auth.username')"
18
- name="login-name"
19
- :error="error.username"
20
- @update:error="(val: boolean) => error.username = val"
21
- />
22
- <SInput
23
- v-model="form.email"
24
- :label="t('email')"
25
- autocomplete="email"
26
- :error="error.email"
27
- @update:error="(val: boolean) => error.email = val"
28
- />
29
- <SInput
30
- v-model="form.password_hash"
31
- :label="t('auth.password')"
32
- type="password"
33
- :error="error.password_hash"
34
- autocomplete="new-password"
35
- @update:error="(val: boolean) => error.password_hash = val"
36
- />
37
-
38
- <div class="s-auth-register__buttons">
39
- <SButton
40
- :disabled="loading"
41
- wide
42
- size="l"
43
- @click="submit"
44
- >{{ t('auth.sign_up') }}
45
- </SButton>
46
- <SButton
47
- wide
48
- size="l"
49
- theme="secondary"
50
- @click="onLoginClick"
51
- >{{ t('auth.log_in') }}
52
- </SButton>
2
+ <ClientOnly>
3
+ <div
4
+ class="s-auth-register"
5
+ :class="{'_loading': loading}"
6
+ >
7
+ <SIcon
8
+ class="s-auth-register__icon"
9
+ name="user-circle"
10
+ size="40"
11
+ />
12
+ <p
13
+ v-if="additionalText"
14
+ class="s-auth-register__text"
15
+ >{{ t(additionalText) }}</p>
16
+ <SInput
17
+ v-model="form.username"
18
+ :label="t('auth.username')"
19
+ name="login-name"
20
+ :error="error.username"
21
+ @update:error="(val: boolean) => error.username = val"
22
+ />
23
+ <SInput
24
+ v-model="form.email"
25
+ :label="t('email')"
26
+ autocomplete="email"
27
+ :error="error.email"
28
+ @update:error="(val: boolean) => error.email = val"
29
+ />
30
+ <SInput
31
+ v-model="form.password_hash"
32
+ :label="t('auth.password')"
33
+ type="password"
34
+ :error="error.password_hash"
35
+ autocomplete="new-password"
36
+ @update:error="(val: boolean) => error.password_hash = val"
37
+ />
38
+
39
+ <div class="s-auth-register__buttons">
40
+ <SButton
41
+ :disabled="loading"
42
+ wide
43
+ size="l"
44
+ @click="submit"
45
+ >{{ t('auth.sign_up') }}
46
+ </SButton>
47
+ <SButton
48
+ wide
49
+ size="l"
50
+ theme="secondary"
51
+ @click="onLoginClick"
52
+ >{{ t('auth.log_in') }}
53
+ </SButton>
54
+ </div>
55
+
56
+ <p class="s-auth-register__agreement">{{ t('auth.agree_begin') }}
57
+ <NuxtLink
58
+ class="s-auth-register__agreement-link"
59
+ to="/terms"
60
+ target="_blank"
61
+ >{{ t('auth.agree_terms')}}
62
+ </NuxtLink>{{ t('auth.agree_and')}}
63
+ <NuxtLink
64
+ class="s-auth-register__agreement-link"
65
+ to="/policy"
66
+ target="_blank"
67
+ >{{ t('auth.agree_policy') }}
68
+ </NuxtLink>
69
+ </p>
53
70
  </div>
54
-
55
- <p class="s-auth-register__agreement">{{ t('auth.agree_begin') }}
56
- <NuxtLink
57
- class="s-auth-register__agreement-link"
58
- to="/terms"
59
- target="_blank"
60
- >{{ t('auth.agree_terms')}}
61
- </NuxtLink>{{ t('auth.agree_and')}}<NuxtLink
62
- class="s-auth-register__agreement-link"
63
- to="/policy"
64
- target="_blank"
65
- >{{ t('auth.agree_policy') }}
66
- </NuxtLink>
67
- </p>
68
- </div>
71
+ </ClientOnly>
69
72
  </template>
70
73
 
71
74
  <script setup lang="ts">
72
75
  import type { IRegistrateForm } from '../../types';
73
76
  import { validateEmail, validatePassword, validateUsername } from '../../runtime';
74
77
  import { AuthorizationApiService } from '~/services/api/authorization.service';
78
+ import { useReCaptcha } from 'vue-recaptcha-v3';
75
79
 
76
80
  defineProps<{
77
81
  additionalText?: string;
78
82
  }>()
79
83
 
80
- const {t} = useI18n();
84
+ const { t } = useI18n();
85
+
86
+ // Правильное использование composable для Vue 3
87
+ const { executeRecaptcha, recaptchaLoaded } = useReCaptcha();
81
88
 
82
89
  const form = ref({
83
90
  username: '',
@@ -104,8 +111,6 @@ const loading = ref(false);
104
111
 
105
112
  const { setErrorState, snackbarText, snackbarTheme, showErrorSnack, resetSnackbar } = useSnackbar();
106
113
 
107
- const { executeRecaptcha } = useGoogleRecaptcha();
108
-
109
114
  function validateForm(): boolean {
110
115
  const { username, email, password_hash } = form.value;
111
116
 
@@ -115,19 +120,12 @@ function validateForm(): boolean {
115
120
  password_hash: !validatePassword(password_hash),
116
121
  };
117
122
 
118
- if (!validateEmail(email)) {
119
- showErrorSnack('error_email');
120
- }
121
- if (!validatePassword(password_hash)) {
122
- showErrorSnack('error_password');
123
- }
124
- if (!validateUsername(username)) {
125
- showErrorSnack('error_username');
126
- }
123
+ if (!validateEmail(email)) showErrorSnack('error_email');
124
+ if (!validatePassword(password_hash)) showErrorSnack('error_password');
125
+ if (!validateUsername(username)) showErrorSnack('error_username');
127
126
 
128
127
  error.value = errors;
129
128
 
130
-
131
129
  return !Object.values(errors).some(Boolean);
132
130
  }
133
131
 
@@ -140,14 +138,21 @@ async function submit() {
140
138
 
141
139
  try {
142
140
  loading.value = true;
143
- const { token } = await executeRecaptcha('submit');
144
- form.value.token = token || '';
141
+
142
+ // Здесь происходит lazy-загрузка скрипта reCAPTCHA (только при submit!)
143
+ await recaptchaLoaded();
144
+ // имя действия для Google Analytics
145
+ form.value.token = await executeRecaptcha('register');
146
+
145
147
  await useUser(AuthorizationApiService).register(form.value);
148
+
146
149
  useAuthPopup().closeAuthPopup();
147
150
  snackbarTheme.value = 'success';
148
151
  snackbarText.value = 'Registration success';
149
152
  } catch (err) {
150
153
  setErrorState(err);
154
+ // Опционально: обработка ошибки reCAPTCHA (например, если загрузка не удалась)
155
+ console.error('reCAPTCHA error:', err);
151
156
  } finally {
152
157
  loading.value = false;
153
158
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "itube-specs",
3
3
  "type": "module",
4
- "version": "0.0.439",
4
+ "version": "0.0.440",
5
5
  "main": "./nuxt.config.ts",
6
6
  "types": "./types/index.d.ts",
7
7
  "scripts": {
@@ -49,6 +49,7 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "@vueform/slider": "2.1.10",
52
- "@vueuse/core": "12.8.2"
52
+ "@vueuse/core": "12.8.2",
53
+ "vue-recaptcha-v3": "^2.0.1"
53
54
  }
54
55
  }