itube-specs 0.0.759 → 0.0.761

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 (61) hide show
  1. package/composables/use-meta.ts +15 -7
  2. package/composables/use-model-filter-chips.ts +50 -46
  3. package/package.json +1 -1
  4. package/components/auth/s-auth-icon.vue +0 -20
  5. package/components/auth/s-auth-login.vue +0 -120
  6. package/components/auth/s-auth-popup.vue +0 -69
  7. package/components/auth/s-auth-recovery.vue +0 -104
  8. package/components/auth/s-auth-register.vue +0 -176
  9. package/components/cards/s-video-mini-card.vue +0 -62
  10. package/components/grids/s-grid-categories.vue +0 -20
  11. package/components/grids/s-grid-channels.vue +0 -23
  12. package/components/grids/s-grid-models.vue +0 -25
  13. package/components/grids/s-grid-playlists.vue +0 -21
  14. package/components/grids/s-grid-videos.vue +0 -75
  15. package/components/page-components/s-breadcrumbs.vue +0 -44
  16. package/components/page-components/s-expand-row.vue +0 -113
  17. package/components/page-components/s-filter-button.vue +0 -41
  18. package/components/page-components/s-filter-chips.vue +0 -34
  19. package/components/page-components/s-filter-page.vue +0 -185
  20. package/components/page-components/s-filter-popup.vue +0 -155
  21. package/components/page-components/s-filter-slider.vue +0 -145
  22. package/components/page-components/s-filter-videos-chips.vue +0 -105
  23. package/components/page-components/s-filter.vue +0 -357
  24. package/components/page-components/s-footer-models.vue +0 -28
  25. package/components/page-components/s-info-grid.vue +0 -89
  26. package/components/page-components/s-info-socials.vue +0 -33
  27. package/components/page-components/s-like.vue +0 -121
  28. package/components/page-components/s-model-filters.vue +0 -235
  29. package/components/page-components/s-navigation-links.vue +0 -63
  30. package/components/page-components/s-pagination.vue +0 -214
  31. package/components/page-components/s-report.vue +0 -267
  32. package/components/page-components/s-section-title.vue +0 -35
  33. package/components/page-components/s-share.vue +0 -122
  34. package/components/playlist/s-playlist-add.vue +0 -299
  35. package/components/playlist/s-playlist-delete-video.vue +0 -79
  36. package/components/playlist/s-playlist-edit.vue +0 -215
  37. package/components/playlist/s-playlist-input.vue +0 -88
  38. package/components/playlist/s-playlist-like.vue.unused +0 -96
  39. package/components/playlist/s-playlist-new.vue.unused +0 -57
  40. package/components/playlist/s-playlist-private-toggle.vue +0 -20
  41. package/components/ui/s-avatar.vue +0 -33
  42. package/components/ui/s-button.vue +0 -51
  43. package/components/ui/s-checkbox.vue +0 -57
  44. package/components/ui/s-chips.vue +0 -142
  45. package/components/ui/s-count.vue +0 -17
  46. package/components/ui/s-dropdown.vue +0 -152
  47. package/components/ui/s-icon.vue +0 -19
  48. package/components/ui/s-img.vue +0 -59
  49. package/components/ui/s-input.vue +0 -181
  50. package/components/ui/s-label.vue +0 -20
  51. package/components/ui/s-link.vue +0 -46
  52. package/components/ui/s-notification.vue +0 -72
  53. package/components/ui/s-popup.vue +0 -119
  54. package/components/ui/s-radio.vue +0 -56
  55. package/components/ui/s-select.vue +0 -105
  56. package/components/ui/s-slider.vue +0 -67
  57. package/components/ui/s-snackbar.vue +0 -27
  58. package/components/ui/s-timestamp.vue +0 -59
  59. package/components/ui/s-toggle.vue +0 -30
  60. package/components/ui/s-tooltip.vue +0 -57
  61. package/components/video/s-video-autoplay.vue +0 -29
@@ -14,7 +14,7 @@ import type { IChipsItem } from '../types';
14
14
  * @param thirdText - третий подставляемый текст
15
15
  * @param fourthText - четвёртый подставляемый текст
16
16
  */
17
- export function useMeta(t, page: string, brandName: string, sortOptions?: IChipsItem[], text?: Ref<string>, secondText?: Ref<string>, thirdText?: Ref<string>, fourthText?: Ref<string>) {
17
+ export function useMeta(t: (key: string, params?: Record<string, unknown>) => string, page: string, brandName: string, sortOptions?: IChipsItem[], text?: Ref<string>, secondText?: Ref<string>, thirdText?: Ref<string>, fourthText?: Ref<string>) {
18
18
  const route = useRoute();
19
19
 
20
20
  const sortType = computed(() => {
@@ -48,12 +48,20 @@ export function useMeta(t, page: string, brandName: string, sortOptions?: IChips
48
48
  const metaTitle = computed(() => getPath('title'));
49
49
  const h1 = computed(() => getPath('h1'));
50
50
 
51
- const meta = computed(() => ({
52
- title: metaTitle.value,
53
- meta: [
54
- { name: 'description', content: getPath('meta_description') },
55
- ],
56
- }));
51
+ const meta = computed(() => {
52
+ const description = getPath('meta_description');
53
+
54
+ return {
55
+ title: metaTitle.value,
56
+ meta: [
57
+ { name: 'description', content: description },
58
+ { property: 'og:title', content: metaTitle.value },
59
+ { property: 'og:description', content: description },
60
+ { name: 'twitter:title', content: metaTitle.value },
61
+ { name: 'twitter:description', content: description },
62
+ ],
63
+ };
64
+ });
57
65
 
58
66
  return {
59
67
  meta,
@@ -1,14 +1,8 @@
1
- import type { IChipsItem, IModelFilter, IModelFilterOptions } from '../types'
2
- import type { LocationQuery } from '#vue-router'
3
- import { getMonth } from '../runtime'
1
+ import type { IChipsItem, IModelFilter, IModelFilterOptions } from '../types';
2
+ import type { LocationQuery } from '#vue-router';
3
+ import { getMonth } from '../runtime';
4
4
  import type { Ref } from 'vue';
5
5
 
6
- /**
7
- * Формирует вычисляемый список чипсов из активных filter_* параметров в query маршрута.
8
- * @param filters - список схем фильтров модели
9
- * @param route - текущий маршрут с query
10
- * @param t - функция перевода (i18n)
11
- */
12
6
  export function useFilterChipsItems(
13
7
  filters: Ref<IModelFilter[]>,
14
8
  route: { query: LocationQuery },
@@ -21,52 +15,58 @@ export function useFilterChipsItems(
21
15
  item
22
16
  .replace('filter_', '')
23
17
  .replace(/_/g, ' ')
24
- )
18
+ );
25
19
 
26
20
  const groups = Object.values(
27
21
  queryItems.reduce((acc: Record<string, string[]>, str: string) => {
28
- const parts = str.split(' ')
29
- const last = parts.at(-1)
22
+ const parts = str.split(' ');
23
+ const last = parts.at(-1);
30
24
 
31
25
  const key =
32
26
  last === 'from' || last === 'to'
33
27
  ? parts.slice(0, -1).join(' ')
34
- : str
28
+ : str;
35
29
 
36
- acc[key] ??= []
30
+ acc[key] ??= [];
37
31
 
38
- if (last === 'from') acc[key].unshift(str)
39
- else acc[key].push(str)
32
+ if (last === 'from') acc[key].unshift(str);
33
+ else acc[key].push(str);
40
34
 
41
- return acc
35
+ return acc;
42
36
  }, {})
43
- )
37
+ );
38
+
39
+ const findFilter = (items: string[]) => {
40
+ const key = items[0].replace(' from', '').replace(' to', '');
41
+ return filters.value.find(f => f.name.replace(/_/g, ' ') === key);
42
+ };
44
43
 
45
44
  const getValue = (item: string, index: number) => {
46
45
  const filter = filters.value.find(filter =>
47
46
  filter.name ===
48
47
  item
49
- .replace(/ /g, '_')
48
+ .replace(/ /g,
49
+ '_')
50
50
  .replace('_from', '')
51
51
  .replace('_to', '')
52
- )
52
+ );
53
53
 
54
54
  const defaultValue =
55
55
  index === 0
56
56
  ? filter?.options[0]
57
- : filter?.options.at(-1)
57
+ : filter?.options.at(-1);
58
58
 
59
- const value = route.query[`filter_${item.replace(/ /g, '_')}`]
59
+ const value = route.query[`filter_${item.replace(/ /g, '_')}`];
60
60
 
61
61
  if (item.includes('month')) {
62
62
  return getMonth(
63
63
  t,
64
64
  Number(value ?? defaultValue?.name) - 1
65
- )
65
+ );
66
66
  }
67
67
 
68
68
  if (!isNaN(Number(value))) {
69
- return value
69
+ return value;
70
70
  }
71
71
 
72
72
  return (
@@ -75,31 +75,35 @@ export function useFilterChipsItems(
75
75
  option.name === value
76
76
  )?.title ??
77
77
  defaultValue?.title
78
- )
79
- }
78
+ );
79
+ };
80
80
 
81
81
  const getValueText = (items: string[]) =>
82
- [...new Set(items.map(getValue))].join(' - ')
83
-
84
- const chipsTitle = (items: string[]) => {
85
- const key = items[0].replace(' from', '')
86
- const filter = filters.value.find(
87
- f => f.name.replace(/_/g, ' ') === key
88
- )
89
-
90
- const text = `${filter?.title}: ${getValueText(items)}`
91
- return text.length > 30 ? getValueText(items) : text
92
- }
93
-
94
- return groups.map(item => ({
95
- title: chipsTitle(item),
96
- value: item.map(
97
- sub => `filter_${sub.replace(/ /g, '_')}`
98
- ),
99
- }))
100
- })
82
+ [...new Set(items.map(getValue).filter(v => v !== undefined && v !== null && v !== ''))].join(' - ');
83
+
84
+ const chipsTitle = (items: string[], filter: IModelFilter) => {
85
+ const valueText = getValueText(items);
86
+ const text = `${filter.title}: ${valueText}`;
87
+ return text.length > 30 ? valueText : text;
88
+ };
89
+
90
+ return groups
91
+ .map(item => {
92
+ const filter = findFilter(item);
93
+ if (!filter) return null;
94
+ const valueText = getValueText(item);
95
+ if (!valueText) return null;
96
+ return {
97
+ title: chipsTitle(item, filter),
98
+ value: item.map(
99
+ sub => `filter_${sub.replace(/ /g, '_')}`
100
+ ),
101
+ };
102
+ })
103
+ .filter((c): c is IChipsItem => c !== null);
104
+ });
101
105
 
102
106
  return {
103
107
  chipsItems,
104
- }
108
+ };
105
109
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "itube-specs",
3
3
  "type": "module",
4
- "version": "0.0.759",
4
+ "version": "0.0.761",
5
5
  "main": "./nuxt.config.ts",
6
6
  "types": "./types/index.d.ts",
7
7
  "scripts": {
@@ -1,20 +0,0 @@
1
- <template>
2
- <div class="s-auth-icon">
3
- <SIcon
4
- class="s-auth-icon__icon"
5
- :name="icon"
6
- size="24"
7
- />
8
- </div>
9
- </template>
10
-
11
- <script setup lang="ts">
12
- const props = withDefaults(defineProps<{
13
- icon?: string
14
- }>(), {
15
- icon: 'user-filled'
16
- })
17
- </script>
18
-
19
- <style scoped lang="scss">
20
- </style>
@@ -1,120 +0,0 @@
1
- <template>
2
- <div
3
- class="s-auth-login"
4
- :class="{'_loading': loading}"
5
- >
6
-
7
- <SAuthIcon class="s-auth-login__icon"/>
8
-
9
- <SInput
10
- v-model="form.username"
11
- :label="t('auth.username')"
12
- :placeholder="t('auth.username')"
13
- hide-label
14
- name="login-name"
15
- :error="error.username"
16
- @update:error="(val: boolean) => error.username = val"
17
- />
18
- <SInput
19
- v-model="form.password_hash"
20
- :label="t('auth.password')"
21
- :placeholder="t('auth.password')"
22
- hide-label
23
- type="password"
24
- :error="error.password_hash"
25
- @update:error="(val: boolean) => error.password_hash = val"
26
- />
27
-
28
- <div class="s-auth-login__buttons">
29
- <SButton
30
- class="s-auth-login__login"
31
- wide
32
- size="l"
33
- :disabled="loading"
34
- theme="primary"
35
- @click="login"
36
- >{{ t('auth.log_in') }}
37
- </SButton>
38
- <button
39
- class="s-auth-login__forgot"
40
- type="button"
41
- @click="onForgotClick"
42
- >
43
- {{ t('auth.forgot') }}
44
- </button>
45
-
46
- <p class="s-auth-login__back">
47
- {{ t('register_text') }}
48
- <button
49
- class="s-auth-login__back-button"
50
- type="button"
51
- @click="onCreateClick"
52
- >
53
- {{ t('auth.sign_up') }}
54
- </button>
55
- </p>
56
- </div>
57
- </div>
58
- </template>
59
-
60
- <script setup lang="ts">
61
- import { validatePassword, validateUsername } from '../../runtime';
62
- import { AuthorizationApiService } from '~/services/api/authorization.service';
63
-
64
- const { t } = useI18n();
65
-
66
- const form = ref({
67
- username: '',
68
- password_hash: '',
69
- });
70
-
71
- const error = ref({
72
- username: false,
73
- password_hash: false,
74
- });
75
-
76
- const emit = defineEmits<{
77
- (eventName: 'forgot'): void
78
- (eventName: 'create'): void
79
- }>();
80
-
81
- function onForgotClick() {
82
- emit('forgot');
83
- }
84
-
85
- function onCreateClick() {
86
- emit('create');
87
- }
88
-
89
- const loading = ref(false);
90
-
91
- const { setErrorState, showError, showSuccess, resetSnackbar } = useSnackbar();
92
-
93
- async function login() {
94
- resetSnackbar();
95
- error.value.username = false;
96
- error.value.password_hash = false;
97
-
98
- if (!validateUsername(form.value.username)) {
99
- error.value.username = true;
100
- showError('error_username');
101
- }
102
- if (!validatePassword(form.value.password_hash)) {
103
- error.value.password_hash = true;
104
- showError('error_password');
105
- }
106
-
107
- if (!error.value.username && !error.value.password_hash) {
108
- try {
109
- loading.value = true;
110
- await useUser(AuthorizationApiService).login(form.value);
111
- useAuthPopup().closeAuthPopup();
112
- showSuccess('Welcome back!');
113
- } catch (error) {
114
- setErrorState(error);
115
- } finally {
116
- loading.value = false;
117
- }
118
- }
119
- }
120
- </script>
@@ -1,69 +0,0 @@
1
- <template>
2
- <div v-if="isAuthPopupOpen" class="s-auth-popup__decorate"/>
3
- <transition mode="out-in">
4
- <SPopup
5
- v-if="currentStep === EAuthSteps.Registration && isAuthPopupOpen"
6
- v-model="isAuthPopupOpen"
7
- transparent-backdrop
8
- :back="isBackShow"
9
- class="s-auth-popup"
10
- @back="currentStep -= 1"
11
- >
12
- <template #title>{{ $t('auth.create_new') }}</template>
13
- <SAuthRegister
14
- :additional-text="additionalText"
15
- @login="onLoginClick"
16
- />
17
- </SPopup>
18
- </transition>
19
-
20
- <transition mode="out-in">
21
- <SPopup
22
- v-if="currentStep === EAuthSteps.Login && isAuthPopupOpen"
23
- v-model="isAuthPopupOpen"
24
- transparent-backdrop
25
- :back="isBackShow"
26
- class="s-auth-popup"
27
- @back="currentStep -= 1"
28
- >
29
- <template #title>{{ $t('auth.welcome_back') }}</template>
30
- <SAuthLogin @forgot="onRecoveryClick" @create="currentStep -= 1"/>
31
- </SPopup>
32
- </transition>
33
-
34
- <transition mode="out-in">
35
- <SPopup
36
- v-if="currentStep === EAuthSteps.Recovery && isAuthPopupOpen"
37
- v-model="isAuthPopupOpen"
38
- transparent-backdrop
39
- :back="isBackShow"
40
- class="s-auth-popup"
41
- @back="currentStep -= 1"
42
- >
43
- <template #title>{{ $t('auth.recovery_title')}}</template>
44
- <SAuthRecovery @login="onLoginClick"/>
45
- </SPopup>
46
- </transition>
47
- </template>
48
-
49
- <script setup lang="ts">
50
- import { EAuthSteps } from '../../runtime';
51
-
52
- const { isAuthPopupOpen, currentStep, additionalText } = useAuthPopup()
53
-
54
- const backShow = ref(false)
55
-
56
- function onLoginClick(): void {
57
- currentStep.value = EAuthSteps.Login
58
- backShow.value = true
59
- }
60
-
61
- function onRecoveryClick(): void {
62
- currentStep.value = EAuthSteps.Recovery
63
- backShow.value = true
64
- }
65
-
66
- const isBackShow = computed(() => {
67
- return currentStep.value !== EAuthSteps.Registration && backShow.value
68
- })
69
- </script>
@@ -1,104 +0,0 @@
1
- <template>
2
- <div
3
- class="s-auth-recovery"
4
- :class="{'_loading': loading}"
5
- >
6
-
7
- <SAuthIcon
8
- class="s-auth-recovery__icon"
9
- icon="envelope"
10
- />
11
-
12
- <p class="s-auth-recovery__text">{{ t('auth.recovery_text') }}</p>
13
- <SInput
14
- v-model="form.email"
15
- :label="$t('email')"
16
- :placeholder="$t('email')"
17
- hide-label
18
- inputmode="email"
19
- autocomplete="email"
20
- :error="error.email"
21
- @update:error="(val: boolean) => error.email = val"
22
- />
23
-
24
- <SButton
25
- class="s-auth-recovery__button"
26
- wide
27
- size="l"
28
- :disabled="loading"
29
- theme="primary"
30
- @click="submit"
31
- >{{ t('auth.get_recovery') }}
32
- </SButton>
33
- <button
34
- class="s-auth-recovery__login"
35
- type="button"
36
- @click="onLoginClick"
37
- >{{ t('auth.back_to_login') }}
38
- </button>
39
- </div>
40
- </template>
41
-
42
- <script setup lang="ts">
43
- import type { IPasswordForm } from '../../types';
44
- import { validateEmail } from '../../runtime';
45
- import { AuthorizationApiService } from '~/services/api/authorization.service';
46
-
47
- const { initRecaptcha, getRecaptchaToken } = useRecaptcha();
48
-
49
- const { t } = useI18n();
50
-
51
- const form = ref({
52
- email: '',
53
- token: '',
54
- } as IPasswordForm)
55
-
56
- const error = ref({
57
- email: false,
58
- });
59
-
60
- const emit = defineEmits<{
61
- (eventName: 'login'): void
62
- }>()
63
-
64
- function onLoginClick() {
65
- emit('login')
66
- }
67
-
68
- const loading = ref(false)
69
-
70
- const { setErrorState, showError, showSuccess, resetSnackbar } = useSnackbar();
71
-
72
- // Загружаем reCAPTCHA при открытии формы (onMounted) — даёт Google время собрать данные о поведении
73
- onMounted(async () => {
74
- try {
75
- await initRecaptcha();
76
- console.log('reCAPTCHA готов для этой формы');
77
- } catch (err) {
78
- console.error('Ошибка инициализации reCAPTCHA:', err);
79
- }
80
- });
81
-
82
- async function submit() {
83
- resetSnackbar()
84
- error.value.email = false;
85
-
86
- if (!validateEmail(form.value.email)) {
87
- error.value.email = true;
88
- showError('error_email');
89
- return;
90
- }
91
-
92
- try {
93
- loading.value = true;
94
- form.value.token = await getRecaptchaToken('password_reset');
95
- await useUser(AuthorizationApiService).password(form.value);
96
- useAuthPopup().closeAuthPopup();
97
- showSuccess('Check your email');
98
- } catch (error) {
99
- setErrorState(error);
100
- } finally {
101
- loading.value = false;
102
- }
103
- }
104
- </script>
@@ -1,176 +0,0 @@
1
- <template>
2
- <ClientOnly>
3
- <div
4
- class="s-auth-register"
5
- :class="{'_loading': loading}"
6
- >
7
- <SAuthIcon class="s-auth-register__icon" />
8
- <p
9
- v-if="additionalText"
10
- class="s-auth-register__text"
11
- >{{ t(additionalText) }}
12
- </p>
13
- <SInput
14
- v-model="form.email"
15
- :placeholder="t('email')"
16
- :label="t('email')"
17
- hide-label
18
- inputmode="email"
19
- autocomplete="email"
20
- :error="error.email"
21
- @update:error="(val: boolean) => error.email = val"
22
- />
23
- <SInput
24
- v-model="form.username"
25
- :label="t('login')"
26
- :placeholder="t('login')"
27
- hide-label
28
- name="login-name"
29
- :error="error.username"
30
- @update:error="(val: boolean) => error.username = val"
31
- />
32
- <SInput
33
- v-model="form.password_hash"
34
- :label="t('auth.password')"
35
- :placeholder="t('auth.password')"
36
- hide-label
37
- type="password"
38
- :error="error.password_hash"
39
- autocomplete="new-password"
40
- @update:error="(val: boolean) => error.password_hash = val"
41
- />
42
-
43
- <div class="s-auth-register__buttons">
44
- <SButton
45
- :disabled="loading"
46
- wide
47
- size="l"
48
- theme="primary"
49
- @click="submit"
50
- >{{ t('auth.sign_up') }}
51
- </SButton>
52
- <p class="s-auth-register__login">
53
- {{ t('login_text') }}
54
- <button
55
- class="s-auth-register__login-button"
56
- type="button"
57
- @click="onLoginClick">
58
- {{ t('auth.log_in') }}
59
- </button>
60
- </p>
61
- </div>
62
-
63
- <p class="s-auth-register__agreement">{{ t('auth.agree_begin') }}
64
- <NuxtLink
65
- class="s-auth-register__agreement-link"
66
- to="/terms"
67
- target="_blank"
68
- >{{ t('auth.agree_terms') }}
69
- </NuxtLink>
70
- {{ t('auth.agree_and') }}
71
- <NuxtLink
72
- class="s-auth-register__agreement-link"
73
- to="/policy"
74
- target="_blank"
75
- >{{ t('auth.agree_policy') }}
76
- </NuxtLink>
77
- </p>
78
- </div>
79
- </ClientOnly>
80
- </template>
81
-
82
- <script setup lang="ts">
83
- import type { IRegistrateForm } from '../../types';
84
- import { validateEmail, validatePassword, validateUsername } from '../../runtime';
85
- import { AuthorizationApiService } from '~/services/api/authorization.service';
86
-
87
- const { initRecaptcha, getRecaptchaToken } = useRecaptcha();
88
-
89
- defineProps<{
90
- additionalText?: string;
91
- }>()
92
-
93
- const { t } = useI18n();
94
-
95
- const form = ref({
96
- username: '',
97
- email: '',
98
- password_hash: '',
99
- token: '',
100
- } as IRegistrateForm)
101
-
102
- const error = ref({
103
- username: false,
104
- email: false,
105
- password_hash: false,
106
- })
107
-
108
- const emit = defineEmits<{
109
- (eventName: 'login'): void
110
- }>()
111
-
112
- function onLoginClick() {
113
- emit('login')
114
- }
115
-
116
- const loading = ref(false);
117
-
118
- const { setErrorState, showError, showSuccess, resetSnackbar } = useSnackbar();
119
- // Загружаем reCAPTCHA при открытии формы (onMounted) — даёт Google время собрать данные о поведении
120
- onMounted(async () => {
121
- try {
122
- await initRecaptcha();
123
- console.log('reCAPTCHA готов для этой формы');
124
- } catch (err) {
125
- console.error('Ошибка инициализации reCAPTCHA:', err);
126
- }
127
- });
128
-
129
- function validateForm(): boolean {
130
- const { username, email, password_hash } = form.value;
131
-
132
- const errors = {
133
- username: !validateUsername(username),
134
- email: !validateEmail(email),
135
- password_hash: !validatePassword(password_hash),
136
- };
137
-
138
- if (!validateEmail(email)) showError('error_email');
139
- if (!validatePassword(password_hash)) showError('error_password');
140
- if (!validateUsername(username)) showError('error_username');
141
-
142
- error.value = errors;
143
-
144
- return !Object.values(errors).some(Boolean);
145
- }
146
-
147
- async function submit() {
148
- resetSnackbar();
149
- if (!validateForm()) return;
150
-
151
- try {
152
- loading.value = true;
153
-
154
- // Уникальное действие для каждой формы
155
- // здесь 'register', в других формах — 'password_reset' или 'contact_form'
156
- form.value.token = await getRecaptchaToken('register');
157
-
158
- await useUser(AuthorizationApiService).register(form.value);
159
-
160
- // Создаем сразу Favorites плейлист, возможно костыль убрать когда будет нормальная логика с беком
161
- // const { FAVORITES_KEY } = useFavorites();
162
- // await PlaylistsApiService.postPlaylist(FAVORITES_KEY, EPlaylistType.Private);
163
-
164
- useAuthPopup().closeAuthPopup();
165
- showSuccess('Registration success');
166
- } catch (err) {
167
- setErrorState(err);
168
- console.error('Ошибка reCAPTCHA или регистрации:', err);
169
- } finally {
170
- loading.value = false;
171
- }
172
- }
173
- </script>
174
-
175
- <style scoped>
176
- </style>