@coopenomics/desktop 2025.11.15-alpha-1 → 2025.11.17-alpha-1
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.
- package/package.json +6 -6
- package/src/app/styles/style.css +5 -0
- package/src/entities/CmdkMenu/model/store.ts +9 -9
- package/src/entities/ConnectionAgreement/api/index.ts +1 -1
- package/src/features/Agreementer/SignAgreementDialog/ui/SignAgreementDialog.vue +1 -1
- package/src/features/Installer/ui/SetVariablesForm/SetVariablesForm.vue +33 -11
- package/src/features/NotificationPermissionDialog/model/index.ts +12 -17
- package/src/features/NotificationPermissionDialog/ui/NotificationPermissionDialog.vue +0 -1
- package/src/features/Union/CooperativeDataForm/ui/CooperativeDataForm.vue +188 -17
- package/src/pages/Cooperative/ListOfMeets/ui/ListOfMeetsPage.vue +3 -3
- package/src/pages/Registrator/SignUp/PayInitial.vue +1 -1
- package/src/pages/Registrator/SignUp/ReadStatement.vue +5 -5
- package/src/pages/Union/ConnectionAgreement/ConnectionAgreementPage.vue +42 -11
- package/src/widgets/ConnectionAgreementStepper/Steps/AgreementStep.vue +24 -3
- package/src/widgets/ConnectionAgreementStepper/Steps/DomainValidationStep.vue +1 -1
- package/src/widgets/ConnectionAgreementStepper/Steps/FormStep.vue +39 -9
- package/src/widgets/ConnectionAgreementStepper/Steps/IntroStep.vue +15 -0
- package/src/widgets/ConnectionAgreementStepper/Steps/UnionMembershipStep.vue +257 -20
- package/src/widgets/ConnectionAgreementStepper/Tariffs/TariffCard.vue +0 -2
- package/src/widgets/Desktop/CmdkMenu/CmdkMenu.vue +1 -5
- package/src/widgets/Desktop/SecondLevelMenuList/SecondLevelMenuList.vue +6 -7
- package/src/widgets/Desktop/WorkspaceMenu/WorkspaceMenu.vue +6 -6
- package/src-pwa/register-service-worker.ts +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coopenomics/desktop",
|
|
3
|
-
"version": "2025.11.
|
|
3
|
+
"version": "2025.11.17-alpha-1",
|
|
4
4
|
"description": "A Desktop Project",
|
|
5
5
|
"productName": "Desktop App",
|
|
6
6
|
"author": "Alex Ant <dacom.dark.sun@gmail.com>",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"start": "node -r ./alias-resolver.js dist/ssr/index.js"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@coopenomics/controller": "2025.11.
|
|
29
|
-
"@coopenomics/notifications": "2025.11.
|
|
30
|
-
"@coopenomics/sdk": "2025.11.
|
|
28
|
+
"@coopenomics/controller": "2025.11.17-alpha-1",
|
|
29
|
+
"@coopenomics/notifications": "2025.11.17-alpha-1",
|
|
30
|
+
"@coopenomics/sdk": "2025.11.17-alpha-1",
|
|
31
31
|
"@dicebear/collection": "^9.0.1",
|
|
32
32
|
"@dicebear/core": "^9.0.1",
|
|
33
33
|
"@editorjs/code": "^2.9.3",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@wharfkit/wallet-plugin-privatekey": "^1.1.0",
|
|
60
60
|
"axios": "^1.2.1",
|
|
61
61
|
"compression": "^1.7.4",
|
|
62
|
-
"cooptypes": "2025.11.
|
|
62
|
+
"cooptypes": "2025.11.17-alpha-1",
|
|
63
63
|
"dompurify": "^3.1.7",
|
|
64
64
|
"dotenv": "^16.4.5",
|
|
65
65
|
"email-regex": "^5.0.0",
|
|
@@ -123,5 +123,5 @@
|
|
|
123
123
|
"npm": ">= 6.13.4",
|
|
124
124
|
"yarn": ">= 1.21.1"
|
|
125
125
|
},
|
|
126
|
-
"gitHead": "
|
|
126
|
+
"gitHead": "2faadae4cfd733890469c17e38e296d3e4cce29c"
|
|
127
127
|
}
|
package/src/app/styles/style.css
CHANGED
|
@@ -69,18 +69,18 @@ export const useCmdkMenuStore = defineStore(namespace, () => {
|
|
|
69
69
|
return shortcuts[pageName];
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
+
// Вычисляем роль пользователя
|
|
73
|
+
const userRole = computed(() =>
|
|
74
|
+
user.isChairman ? 'chairman' : user.isMember ? 'member' : 'user'
|
|
75
|
+
);
|
|
76
|
+
|
|
72
77
|
// Группировка воркспейсов с их страницами
|
|
73
78
|
const groupedItems = computed<GroupedItem[]>(() => {
|
|
74
|
-
const userRole = user.isChairman
|
|
75
|
-
? 'chairman'
|
|
76
|
-
: user.isMember
|
|
77
|
-
? 'member'
|
|
78
|
-
: 'user';
|
|
79
79
|
|
|
80
80
|
return desktop.workspaceMenus
|
|
81
81
|
.filter(
|
|
82
82
|
(item) =>
|
|
83
|
-
item.meta?.roles?.includes(userRole) ||
|
|
83
|
+
item.meta?.roles?.includes(userRole.value) ||
|
|
84
84
|
item.meta?.roles === undefined ||
|
|
85
85
|
item.meta?.roles.length === 0
|
|
86
86
|
)
|
|
@@ -93,14 +93,14 @@ const groupedItems = computed<GroupedItem[]>(() => {
|
|
|
93
93
|
.filter((page: any) => {
|
|
94
94
|
// Фильтрация по ролям, условиям и скрытым страницам
|
|
95
95
|
const rolesMatch =
|
|
96
|
-
page.meta?.roles?.includes(
|
|
96
|
+
page.meta?.roles?.includes(userRole.value) ||
|
|
97
97
|
!page.meta?.roles ||
|
|
98
98
|
page.meta.roles.length === 0;
|
|
99
99
|
const conditionMatch = page.meta?.conditions
|
|
100
|
-
|
|
100
|
+
? evaluateCondition(page.meta.conditions, {
|
|
101
101
|
isCoop: user.privateAccount.value?.type === 'organization' &&
|
|
102
102
|
user.privateAccount.value?.organization_data?.type?.toUpperCase() === 'COOP',
|
|
103
|
-
userRole:
|
|
103
|
+
userRole: userRole.value,
|
|
104
104
|
userAccount: user.privateAccount.value,
|
|
105
105
|
coopname: info.coopname,
|
|
106
106
|
})
|
|
@@ -16,7 +16,7 @@ export async function getCurrentInstance(): Promise<CurrentInstance | null> {
|
|
|
16
16
|
|
|
17
17
|
return instance;
|
|
18
18
|
} catch (error) {
|
|
19
|
-
console.
|
|
19
|
+
console.warn('Инстанс не получен. Продолжаем работу без него:', error);
|
|
20
20
|
return null;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -4,7 +4,7 @@ q-dialog(v-model="show" persistent :maximized="true" )
|
|
|
4
4
|
div(style="padding-bottom: 50px; padding-top: 50px;").row.justify-center
|
|
5
5
|
q-card(flat).col-md-8.col-col-xs-12
|
|
6
6
|
Loader(v-if="isLoading" :text='`Формируем документ...`')
|
|
7
|
-
Form(:handler-submit="sign" :is-submitting="isSubmitting" :showSubmit="!isLoading" :showCancel="false" :button-submit-txt="'Подписать
|
|
7
|
+
Form(:handler-submit="sign" :is-submitting="isSubmitting" :showSubmit="!isLoading" :showCancel="false" :button-submit-txt="'Подписать'" @cancel="clear").q-pa-lg
|
|
8
8
|
slot
|
|
9
9
|
</template>
|
|
10
10
|
|
|
@@ -5,42 +5,51 @@ div
|
|
|
5
5
|
q-card-section
|
|
6
6
|
div.text-h6 Наименование
|
|
7
7
|
div
|
|
8
|
-
q-badge.q-mr-sm.q-mb-md
|
|
9
|
-
| -
|
|
8
|
+
q-badge.q-mr-sm.q-mb-md ОПФ+
|
|
9
|
+
| - основа наименования
|
|
10
|
+
.text-caption.text-grey Например: "Потребительский Кооператив Социального Комплекса" или "Потребительский Кооператив"
|
|
11
|
+
|
|
10
12
|
q-input(
|
|
11
13
|
autofocus
|
|
12
14
|
v-model="installStore.vars.name"
|
|
13
|
-
label="
|
|
15
|
+
label="Собственное название организации"
|
|
14
16
|
placeholder="Ромашка"
|
|
15
17
|
standout="bg-teal text-white"
|
|
18
|
+
hint="Название без кавычек, которое будет добавляться к основе"
|
|
19
|
+
:rules="[val => notEmpty(val)]"
|
|
16
20
|
)
|
|
17
21
|
|
|
18
22
|
q-input.q-mt-md(
|
|
19
23
|
v-model="installStore.vars.full_abbr"
|
|
20
|
-
label="
|
|
21
|
-
placeholder="Потребительский Кооператив"
|
|
24
|
+
label="Основа наименования в именительном падеже"
|
|
25
|
+
placeholder="Потребительский Кооператив Социального Комплекса"
|
|
22
26
|
standout="bg-teal text-white"
|
|
27
|
+
:rules="[val => notEmpty(val)]"
|
|
23
28
|
)
|
|
29
|
+
.text-caption.text-grey Вся часть до названия. Если уточнения нет - просто ОПФ
|
|
24
30
|
|
|
25
31
|
q-input.q-mt-md(
|
|
26
32
|
v-model="installStore.vars.full_abbr_genitive"
|
|
27
|
-
label="
|
|
28
|
-
placeholder="Потребительского Кооператива"
|
|
33
|
+
label="Основа наименования в родительном падеже"
|
|
34
|
+
placeholder="Потребительского Кооператива Социального Комплекса"
|
|
29
35
|
standout="bg-teal text-white"
|
|
36
|
+
:rules="[val => notEmpty(val)]"
|
|
30
37
|
)
|
|
31
38
|
|
|
32
39
|
q-input.q-mt-md(
|
|
33
40
|
v-model="installStore.vars.full_abbr_dative"
|
|
34
|
-
label="
|
|
35
|
-
placeholder="Потребительскому Кооперативу"
|
|
41
|
+
label="Основа наименования в дательном падеже"
|
|
42
|
+
placeholder="Потребительскому Кооперативу Социального Комплекса"
|
|
36
43
|
standout="bg-teal text-white"
|
|
44
|
+
:rules="[val => notEmpty(val)]"
|
|
37
45
|
)
|
|
38
46
|
|
|
39
47
|
q-input.q-mt-md(
|
|
40
48
|
v-model="installStore.vars.short_abbr"
|
|
41
|
-
label="Краткая
|
|
42
|
-
placeholder="
|
|
49
|
+
label="Краткая аббревиатура основы наименования"
|
|
50
|
+
placeholder="ПКСК"
|
|
43
51
|
standout="bg-teal text-white"
|
|
52
|
+
:rules="[val => notEmpty(val)]"
|
|
44
53
|
)
|
|
45
54
|
|
|
46
55
|
q-card(flat).q-mb-md
|
|
@@ -53,6 +62,7 @@ div
|
|
|
53
62
|
placeholder="https://example.com/statute.pdf"
|
|
54
63
|
type="url"
|
|
55
64
|
standout="bg-teal text-white"
|
|
65
|
+
:rules="[val => notEmpty(val)]"
|
|
56
66
|
)
|
|
57
67
|
|
|
58
68
|
q-card(flat).q-mb-md
|
|
@@ -90,6 +100,7 @@ div
|
|
|
90
100
|
label="Email по вопросам конфиденциальности"
|
|
91
101
|
type="email"
|
|
92
102
|
standout="bg-teal text-white"
|
|
103
|
+
:rules="[val => notEmpty(val)]"
|
|
93
104
|
)
|
|
94
105
|
|
|
95
106
|
//- q-input.q-mt-md(
|
|
@@ -111,12 +122,14 @@ div
|
|
|
111
122
|
label="Номер протокола"
|
|
112
123
|
:placeholder="getCurrentProtocolNumber"
|
|
113
124
|
standout="bg-teal text-white"
|
|
125
|
+
:rules="[val => notEmpty(val)]"
|
|
114
126
|
)
|
|
115
127
|
q-input.q-mt-sm(
|
|
116
128
|
v-model="installStore.vars.wallet_agreement.protocol_day_month_year"
|
|
117
129
|
label="Дата протокола"
|
|
118
130
|
:placeholder="getCurrentProtocolDate"
|
|
119
131
|
standout="bg-teal text-white"
|
|
132
|
+
:rules="[val => notEmpty(val)]"
|
|
120
133
|
)
|
|
121
134
|
|
|
122
135
|
div.q-mt-md
|
|
@@ -126,12 +139,14 @@ div
|
|
|
126
139
|
label="Номер протокола"
|
|
127
140
|
:placeholder="getCurrentProtocolNumber"
|
|
128
141
|
standout="bg-teal text-white"
|
|
142
|
+
:rules="[val => notEmpty(val)]"
|
|
129
143
|
)
|
|
130
144
|
q-input.q-mt-sm(
|
|
131
145
|
v-model="installStore.vars.signature_agreement.protocol_day_month_year"
|
|
132
146
|
label="Дата протокола"
|
|
133
147
|
:placeholder="getCurrentProtocolDate"
|
|
134
148
|
standout="bg-teal text-white"
|
|
149
|
+
:rules="[val => notEmpty(val)]"
|
|
135
150
|
)
|
|
136
151
|
|
|
137
152
|
div.q-mt-md
|
|
@@ -141,12 +156,14 @@ div
|
|
|
141
156
|
label="Номер протокола"
|
|
142
157
|
:placeholder="getCurrentProtocolNumber"
|
|
143
158
|
standout="bg-teal text-white"
|
|
159
|
+
:rules="[val => notEmpty(val)]"
|
|
144
160
|
)
|
|
145
161
|
q-input.q-mt-sm(
|
|
146
162
|
v-model="installStore.vars.privacy_agreement.protocol_day_month_year"
|
|
147
163
|
label="Дата протокола"
|
|
148
164
|
:placeholder="getCurrentProtocolDate"
|
|
149
165
|
standout="bg-teal text-white"
|
|
166
|
+
:rules="[val => notEmpty(val)]"
|
|
150
167
|
)
|
|
151
168
|
|
|
152
169
|
div.q-mt-md
|
|
@@ -156,12 +173,14 @@ div
|
|
|
156
173
|
label="Номер протокола"
|
|
157
174
|
:placeholder="getCurrentProtocolNumber"
|
|
158
175
|
standout="bg-teal text-white"
|
|
176
|
+
:rules="[val => notEmpty(val)]"
|
|
159
177
|
)
|
|
160
178
|
q-input.q-mt-sm(
|
|
161
179
|
v-model="installStore.vars.user_agreement.protocol_day_month_year"
|
|
162
180
|
label="Дата протокола"
|
|
163
181
|
:placeholder="getCurrentProtocolDate"
|
|
164
182
|
standout="bg-teal text-white"
|
|
183
|
+
:rules="[val => notEmpty(val)]"
|
|
165
184
|
)
|
|
166
185
|
|
|
167
186
|
div.q-mt-md
|
|
@@ -171,12 +190,14 @@ div
|
|
|
171
190
|
label="Номер протокола"
|
|
172
191
|
:placeholder="getCurrentProtocolNumber"
|
|
173
192
|
standout="bg-teal text-white"
|
|
193
|
+
:rules="[val => notEmpty(val)]"
|
|
174
194
|
)
|
|
175
195
|
q-input.q-mt-sm(
|
|
176
196
|
v-model="installStore.vars.participant_application.protocol_day_month_year"
|
|
177
197
|
label="Дата протокола"
|
|
178
198
|
:placeholder="getCurrentProtocolDate"
|
|
179
199
|
standout="bg-teal text-white"
|
|
200
|
+
:rules="[val => notEmpty(val)]"
|
|
180
201
|
)
|
|
181
202
|
|
|
182
203
|
div.flex.justify-between.q-mt-md
|
|
@@ -191,6 +212,7 @@ import { useInstallCooperativeStore } from 'src/entities/Installer/model';
|
|
|
191
212
|
import { useSystemStore } from 'src/entities/System/model';
|
|
192
213
|
import { FailAlert, SuccessAlert } from 'src/shared/api';
|
|
193
214
|
import { useInstallCooperative } from '../../model';
|
|
215
|
+
import { notEmpty } from 'src/shared/lib/utils';
|
|
194
216
|
import { ref, onMounted, computed } from 'vue';
|
|
195
217
|
|
|
196
218
|
const installStore = useInstallCooperativeStore()
|
|
@@ -78,31 +78,26 @@ export function useNotificationPermissionDialog() {
|
|
|
78
78
|
|
|
79
79
|
// Обработка согласия пользователя
|
|
80
80
|
const handleAllow = async () => {
|
|
81
|
+
// Немедленно закрываем диалог и сохраняем выбор пользователя
|
|
82
|
+
saveChoice('granted');
|
|
83
|
+
hideDialog();
|
|
84
|
+
|
|
85
|
+
// Выполняем подписку в фоне
|
|
81
86
|
try {
|
|
82
|
-
|
|
83
|
-
console.log('handleAllow');
|
|
84
|
-
// Подписываемся на уведомления (это включает запрос разрешения)
|
|
87
|
+
console.log('handleAllow - начинаем фоновую подписку');
|
|
85
88
|
const success = await subscribe();
|
|
86
89
|
console.log('success', success);
|
|
87
|
-
if (success) {
|
|
88
|
-
console.log('saveChoice
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
hideDialog();
|
|
92
|
-
} else {
|
|
93
|
-
console.log('saveChoice denied');
|
|
94
|
-
// Если подписка не удалась, но пользователь согласился,
|
|
95
|
-
// все равно сохраняем выбор чтобы не показывать диалог снова
|
|
90
|
+
if (!success) {
|
|
91
|
+
console.log('saveChoice denied - подписка не удалась');
|
|
92
|
+
// Если подписка не удалась, меняем выбор на denied
|
|
93
|
+
// чтобы диалог мог появиться снова при необходимости
|
|
96
94
|
saveChoice('denied');
|
|
97
|
-
hideDialog();
|
|
98
95
|
}
|
|
99
96
|
} catch (error) {
|
|
100
97
|
console.error('Ошибка при разрешении уведомлений:', error);
|
|
101
|
-
console.log('saveChoice denied');
|
|
98
|
+
console.log('saveChoice denied - ошибка подписки');
|
|
99
|
+
// При ошибке тоже меняем на denied
|
|
102
100
|
saveChoice('denied');
|
|
103
|
-
hideDialog();
|
|
104
|
-
} finally {
|
|
105
|
-
store.isPermissionDialogProcessing = false;
|
|
106
101
|
}
|
|
107
102
|
};
|
|
108
103
|
|
|
@@ -1,23 +1,87 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
2
|
div
|
|
3
|
-
Form(:handler-submit="saveData" :showCancel="
|
|
4
|
-
q-input(standout="bg-teal text-white" hint="domovoy.com или coop.domovoy.com" label="Домен или поддомен для запуска" v-model="formData.announce" :rules="[val => notEmpty(val), val => isDomain(val)]")
|
|
3
|
+
Form(:handler-submit="saveData" :showCancel="true" :button-cancel-txt="'Назад'" :button-submit-txt="'Продолжить'" @cancel="handleBack").q-gutter-md
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
//- Домен кооператива
|
|
6
|
+
.form-section.q-mb-lg
|
|
7
|
+
.section-header.q-mb-md
|
|
8
|
+
.section-title
|
|
9
|
+
q-icon(name="domain" size="20px" color="primary").q-mr-sm
|
|
10
|
+
span.text-subtitle1.text-weight-medium Домен кооператива
|
|
11
|
+
.section-description.text-body2.q-mt-sm
|
|
12
|
+
| Укажите домен или поддомен, на котором будет работать ваш кооператив
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
q-input.form-input(
|
|
15
|
+
standout="bg-teal text-white"
|
|
16
|
+
hint="domovoy.com или coop.domovoy.com"
|
|
17
|
+
label="Домен или поддомен для запуска"
|
|
18
|
+
v-model="formData.announce"
|
|
19
|
+
:rules="[val => notEmpty(val), val => isDomain(val)]"
|
|
20
|
+
)
|
|
13
21
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
22
|
+
//- Финансовые параметры
|
|
23
|
+
.form-section.q-mb-lg
|
|
24
|
+
.section-header.q-mb-md
|
|
25
|
+
.section-title
|
|
26
|
+
q-icon(name="account_balance_wallet" size="20px" color="secondary").q-mr-sm
|
|
27
|
+
span.text-subtitle1.text-weight-medium Финансовые параметры
|
|
28
|
+
.section-description.text-body2.q-mt-sm
|
|
29
|
+
| Введите вступительные и минимальные паевые взносы пайщиков. Эти параметры будут должны быть указаны в уставных документах кооператива.
|
|
17
30
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
31
|
+
.financial-grid
|
|
32
|
+
.grid-section.q-mb-md
|
|
33
|
+
.subsection-title.text-body1.text-weight-medium.q-mb-sm Для физических лиц и ИП
|
|
34
|
+
.input-row.q-mb-sm
|
|
35
|
+
q-input.form-input(
|
|
36
|
+
standout="bg-teal text-white"
|
|
37
|
+
placeholder="100"
|
|
38
|
+
label="Вступительный взнос"
|
|
39
|
+
v-model="formData.initial"
|
|
40
|
+
type="number"
|
|
41
|
+
:min="0"
|
|
42
|
+
:rules="[val => notEmpty(val)]"
|
|
43
|
+
)
|
|
44
|
+
template(#append)
|
|
45
|
+
span.text-overline RUB
|
|
46
|
+
.input-row
|
|
47
|
+
q-input.form-input(
|
|
48
|
+
standout="bg-teal text-white"
|
|
49
|
+
label="Минимальный паевый взнос"
|
|
50
|
+
placeholder="300"
|
|
51
|
+
v-model="formData.minimum"
|
|
52
|
+
type="number"
|
|
53
|
+
:min="0"
|
|
54
|
+
:rules="[val => notEmpty(val)]"
|
|
55
|
+
)
|
|
56
|
+
template(#append)
|
|
57
|
+
span.text-overline RUB
|
|
58
|
+
|
|
59
|
+
.grid-section
|
|
60
|
+
.subsection-title.text-body1.text-weight-medium.q-mb-sm Для организаций
|
|
61
|
+
.input-row.q-mb-sm
|
|
62
|
+
q-input.form-input(
|
|
63
|
+
standout="bg-teal text-white"
|
|
64
|
+
placeholder="1000"
|
|
65
|
+
label="Вступительный взнос"
|
|
66
|
+
v-model="formData.org_initial"
|
|
67
|
+
type="number"
|
|
68
|
+
:min="0"
|
|
69
|
+
:rules="[val => notEmpty(val)]"
|
|
70
|
+
)
|
|
71
|
+
template(#append)
|
|
72
|
+
span.text-overline RUB
|
|
73
|
+
.input-row
|
|
74
|
+
q-input.form-input(
|
|
75
|
+
standout="bg-teal text-white"
|
|
76
|
+
placeholder="3000"
|
|
77
|
+
label="Минимальный паевый взнос"
|
|
78
|
+
v-model="formData.org_minimum"
|
|
79
|
+
type="number"
|
|
80
|
+
:min="0"
|
|
81
|
+
:rules="[val => notEmpty(val)]"
|
|
82
|
+
)
|
|
83
|
+
template(#append)
|
|
84
|
+
span.text-overline RUB
|
|
21
85
|
</template>
|
|
22
86
|
<script lang="ts" setup>
|
|
23
87
|
import { ref, watch } from 'vue'
|
|
@@ -27,7 +91,7 @@ import { useConnectionAgreementStore } from 'src/entities/ConnectionAgreement';
|
|
|
27
91
|
import type { ICooperativeFormData } from 'src/entities/ConnectionAgreement/model/types';
|
|
28
92
|
|
|
29
93
|
|
|
30
|
-
const emit = defineEmits(['continue'])
|
|
94
|
+
const emit = defineEmits(['continue', 'back'])
|
|
31
95
|
|
|
32
96
|
const connectionAgreement = useConnectionAgreementStore()
|
|
33
97
|
|
|
@@ -56,8 +120,8 @@ const syncFormData = () => {
|
|
|
56
120
|
connectionAgreement.setFormData(formData.value)
|
|
57
121
|
}
|
|
58
122
|
|
|
59
|
-
const
|
|
60
|
-
emit('
|
|
123
|
+
const handleBack = () => {
|
|
124
|
+
emit('back')
|
|
61
125
|
}
|
|
62
126
|
|
|
63
127
|
const saveData = async () => {
|
|
@@ -67,3 +131,110 @@ const saveData = async () => {
|
|
|
67
131
|
emit('continue', formData.value)
|
|
68
132
|
}
|
|
69
133
|
</script>
|
|
134
|
+
|
|
135
|
+
<style scoped>
|
|
136
|
+
.form-section {
|
|
137
|
+
padding: 1.5rem;
|
|
138
|
+
border-radius: 16px;
|
|
139
|
+
border: 1px solid rgba(0, 0, 0, 0.05);
|
|
140
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.section-header {
|
|
144
|
+
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
|
145
|
+
padding-bottom: 1rem;
|
|
146
|
+
display: block;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.section-title {
|
|
150
|
+
display: flex;
|
|
151
|
+
align-items: center;
|
|
152
|
+
margin-bottom: 0.25rem;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.section-description {
|
|
156
|
+
line-height: 1.5;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.financial-grid {
|
|
160
|
+
display: grid;
|
|
161
|
+
grid-template-columns: 1fr 1fr;
|
|
162
|
+
gap: 2rem;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.grid-section {
|
|
166
|
+
padding: 1rem;
|
|
167
|
+
border-radius: 12px;
|
|
168
|
+
border: 1px solid rgba(0, 0, 0, 0.03);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.subsection-title {
|
|
172
|
+
color: var(--q-primary);
|
|
173
|
+
border-bottom: 2px solid var(--q-primary);
|
|
174
|
+
padding-bottom: 0.5rem;
|
|
175
|
+
margin-bottom: 1rem;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.input-row {
|
|
179
|
+
margin-bottom: 1rem;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.input-row:last-child {
|
|
183
|
+
margin-bottom: 0;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.form-input {
|
|
187
|
+
margin-bottom: 0;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/* Разделитель между секциями */
|
|
191
|
+
.form-section + .form-section {
|
|
192
|
+
margin-top: 2rem;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/* Адаптивность */
|
|
196
|
+
@media (max-width: 768px) {
|
|
197
|
+
.financial-grid {
|
|
198
|
+
grid-template-columns: 1fr;
|
|
199
|
+
gap: 1.5rem;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.form-section {
|
|
203
|
+
padding: 1.25rem;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
@media (max-width: 480px) {
|
|
208
|
+
.form-section {
|
|
209
|
+
padding: 1rem;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.section-title {
|
|
213
|
+
flex-direction: column;
|
|
214
|
+
gap: 0.5rem;
|
|
215
|
+
text-align: center;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.section-header {
|
|
219
|
+
text-align: center;
|
|
220
|
+
display: block !important;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.section-description {
|
|
224
|
+
display: block !important;
|
|
225
|
+
width: 100% !important;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.financial-grid {
|
|
229
|
+
gap: 1rem;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.grid-section {
|
|
233
|
+
padding: 0.75rem;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.subsection-title {
|
|
237
|
+
font-size: 1rem;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
</style>
|
|
@@ -22,7 +22,7 @@ const route = useRoute();
|
|
|
22
22
|
const coopname = computed(() => route.params.coopname as string);
|
|
23
23
|
const meetStore = useMeetStore();
|
|
24
24
|
|
|
25
|
-
const
|
|
25
|
+
const currentUser = useCurrentUser();
|
|
26
26
|
|
|
27
27
|
// Данные напрямую из стора
|
|
28
28
|
const meets = computed(() => meetStore.meets);
|
|
@@ -45,7 +45,7 @@ const loadMeets = async () => {
|
|
|
45
45
|
|
|
46
46
|
// Проверка разрешений
|
|
47
47
|
const canCreateMeet = computed(() => {
|
|
48
|
-
return isMember || isChairman;
|
|
48
|
+
return currentUser.isMember || currentUser.isChairman;
|
|
49
49
|
});
|
|
50
50
|
|
|
51
51
|
// Функция для регистрации кнопки
|
|
@@ -55,7 +55,7 @@ const registerCreateMeetButton = () => {
|
|
|
55
55
|
id: CREATE_MEET_BUTTON_ID,
|
|
56
56
|
component: CreateMeetButton,
|
|
57
57
|
props: {
|
|
58
|
-
isChairman: isChairman,
|
|
58
|
+
isChairman: currentUser.isChairman,
|
|
59
59
|
},
|
|
60
60
|
order: 1,
|
|
61
61
|
});
|
|
@@ -4,7 +4,7 @@ q-step(
|
|
|
4
4
|
title='Оплатите вступительный взнос',
|
|
5
5
|
:done='store.isStepDone("PayInitial")'
|
|
6
6
|
)
|
|
7
|
-
div(v-if='payment?.payment_details?.amount_without_fee')
|
|
7
|
+
div(v-if='payment?.payment_details?.amount_without_fee').q-pa-sm
|
|
8
8
|
p Пожалуйста, совершите оплату регистрационного взноса {{ payment.payment_details.amount_without_fee }}. Комиссия провайдера {{ payment.payment_details.fact_fee_percent }}%, всего к оплате: {{ payment.payment_details.amount_plus_fee }}.
|
|
9
9
|
.q-mt-md
|
|
10
10
|
span.text-bold Внимание!
|
|
@@ -13,26 +13,26 @@ div
|
|
|
13
13
|
div(ref='statementDiv' v-if='!isLoading' v-html='html').store.statement
|
|
14
14
|
|
|
15
15
|
div(v-if='!isLoading').q-gutter-sm
|
|
16
|
-
q-checkbox(v-model='store.state.agreements.digital_signature'
|
|
16
|
+
q-checkbox(v-model='store.state.agreements.digital_signature').full-width
|
|
17
17
|
| Я прочитал и принимаю
|
|
18
18
|
ReadAgreementDialog(v-if="signatureAgreement" :agreement="signatureAgreement" v-model:agree="store.state.agreements.digital_signature" text="положение о порядке и правилах использования простой электронной подписи")
|
|
19
19
|
AgreementReader(:agreement="signatureAgreement").q-mb-lg
|
|
20
20
|
|
|
21
|
-
q-checkbox(v-model='store.state.agreements.wallet'
|
|
21
|
+
q-checkbox(v-model='store.state.agreements.wallet').full-width
|
|
22
22
|
| Я прочитал и принимаю
|
|
23
23
|
ReadAgreementDialog(v-if="walletAgreement" :agreement="walletAgreement" v-model:agree="store.state.agreements.wallet" text="положение о целевой потребительской программе 'Цифровой Кошелёк'")
|
|
24
24
|
AgreementReader(:agreement="walletAgreement").q-mb-lg
|
|
25
25
|
|
|
26
|
-
q-checkbox(v-model='store.state.agreements.user'
|
|
26
|
+
q-checkbox(v-model='store.state.agreements.user').full-width
|
|
27
27
|
| Я прочитал и принимаю
|
|
28
28
|
ReadAgreementDialog(v-if="userAgreement" :agreement="userAgreement" v-model:agree="store.state.agreements.user" text="пользовательское соглашение")
|
|
29
29
|
AgreementReader(:agreement="userAgreement").q-mb-lg
|
|
30
30
|
|
|
31
|
-
q-checkbox(v-model='store.state.agreements.ustav'
|
|
31
|
+
q-checkbox(v-model='store.state.agreements.ustav').full-width
|
|
32
32
|
| Я прочитал и принимаю
|
|
33
33
|
|
|
34
34
|
a(v-if='hasStatuteLink' @click.stop='(event) => event.stopPropagation()' :href='statuteLink' target='_blank').q-ml-xs Устав кооператива
|
|
35
|
-
|
|
35
|
+
span(v-else).q-ml-xs Устав кооператива
|
|
36
36
|
|
|
37
37
|
div(v-if="!isLoading").q-mt-lg
|
|
38
38
|
q-btn.col-md-6.col-xs-12(flat @click='back')
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
div.row
|
|
2
|
+
div.row
|
|
3
3
|
div.col-md-12.col-xs-12
|
|
4
4
|
// Лоадер пока идет загрузка данных
|
|
5
5
|
WindowLoader(v-if="isLoading", text="Загрузка данных подключения...")
|
|
@@ -104,24 +104,55 @@ const init = async () => {
|
|
|
104
104
|
isLoading.value = false;
|
|
105
105
|
return;
|
|
106
106
|
}
|
|
107
|
+
console.log('SYSTEM.info.is_unioned', system.info.is_unioned, connectionAgreement.isInitialized);
|
|
108
|
+
|
|
109
|
+
// Запускаем автообновление инстанса каждые 30 секунд (включает начальную загрузку)
|
|
110
|
+
stopInstanceRefresh = await connectionAgreement.startInstanceAutoRefresh(30000);
|
|
111
|
+
|
|
112
|
+
// Ждем загрузки данных инстанса перед определением шага
|
|
113
|
+
if (connectionAgreement.currentInstance === null) {
|
|
114
|
+
await new Promise<void>((resolve) => {
|
|
115
|
+
const unwatch = watch(
|
|
116
|
+
() => connectionAgreement.currentInstance,
|
|
117
|
+
(instance) => {
|
|
118
|
+
if (instance !== null) {
|
|
119
|
+
unwatch();
|
|
120
|
+
resolve();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
107
126
|
|
|
108
127
|
// Инициализируем persistent store если он еще не инициализирован
|
|
109
128
|
if (!connectionAgreement.isInitialized) {
|
|
110
129
|
connectionAgreement.setInitialized(true);
|
|
130
|
+
}
|
|
111
131
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
// Если
|
|
118
|
-
|
|
132
|
+
const instance = connectionAgreement.currentInstance;
|
|
133
|
+
|
|
134
|
+
// Определяем шаг на основе текущего прогресса установки (при каждом заходе)
|
|
135
|
+
if (instance && typeof instance.progress === 'number') {
|
|
136
|
+
if (instance.progress > 0) {
|
|
137
|
+
// Если установка уже идет (прогресс > 0), переходим к шагу установки
|
|
138
|
+
console.log('🔄 Установка уже идет, прогресс:', instance.progress, '→ шаг 6');
|
|
139
|
+
connectionAgreement.setCurrentStep(6);
|
|
140
|
+
} else if (instance.progress === 0) {
|
|
141
|
+
// Если установки еще нет, начинаем с начала
|
|
142
|
+
if (system.info.is_unioned) {
|
|
143
|
+
// Если кооператив не является членом союза, начинаем с нулевого шага
|
|
144
|
+
connectionAgreement.setCurrentStep(0);
|
|
145
|
+
} else {
|
|
146
|
+
// Если кооператив уже член союза, начинаем с первого шага
|
|
147
|
+
connectionAgreement.setCurrentStep(1);
|
|
148
|
+
}
|
|
119
149
|
}
|
|
150
|
+
} else {
|
|
151
|
+
// Если данные еще не загружены, начинаем с шага 1 по умолчанию
|
|
152
|
+
console.log('⏳ Данные инстанса еще не загружены, устанавливаем шаг 1 по умолчанию');
|
|
153
|
+
connectionAgreement.setCurrentStep(1);
|
|
120
154
|
}
|
|
121
155
|
|
|
122
|
-
// Запускаем автообновление инстанса каждые 30 секунд (включает начальную загрузку)
|
|
123
|
-
stopInstanceRefresh = await connectionAgreement.startInstanceAutoRefresh(30000);
|
|
124
|
-
|
|
125
156
|
// Скрываем лоадер после загрузки данных
|
|
126
157
|
isLoading.value = false;
|
|
127
158
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed, withDefaults } from 'vue'
|
|
2
|
+
import { computed, ref, withDefaults } from 'vue'
|
|
3
3
|
import type { IStepProps } from '../model/types'
|
|
4
4
|
import { DocumentHtmlReader } from 'src/shared/ui/DocumentHtmlReader'
|
|
5
5
|
import { Loader } from 'src/shared/ui/Loader'
|
|
@@ -15,8 +15,23 @@ const connectionAgreement = useConnectionAgreementStore()
|
|
|
15
15
|
|
|
16
16
|
const isActive = computed(() => props.isActive)
|
|
17
17
|
const isDone = computed(() => props.isDone)
|
|
18
|
+
const isSigning = ref(false)
|
|
19
|
+
|
|
20
|
+
// Проверяем, готов ли документ для подписания
|
|
21
|
+
const isDocumentReady = computed(() => {
|
|
22
|
+
return connectionAgreement.document && connectionAgreement.document.sign
|
|
23
|
+
})
|
|
18
24
|
|
|
19
25
|
const handleSign = async () => {
|
|
26
|
+
if (isSigning.value) return // Предотвращаем повторные клики
|
|
27
|
+
|
|
28
|
+
// Дополнительная проверка готовности документа
|
|
29
|
+
if (!isDocumentReady.value) {
|
|
30
|
+
console.warn('⚠️ Документ еще не готов для подписания')
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
isSigning.value = true
|
|
20
35
|
try {
|
|
21
36
|
console.log('📝 AgreementStep: Подписываем документ')
|
|
22
37
|
await connectionAgreement.signDocument()
|
|
@@ -67,14 +82,17 @@ const handleSign = async () => {
|
|
|
67
82
|
} catch (error) {
|
|
68
83
|
console.error('❌ Ошибка при подписании или отправке в блокчейн:', error)
|
|
69
84
|
throw error
|
|
85
|
+
} finally {
|
|
86
|
+
isSigning.value = false
|
|
70
87
|
}
|
|
71
88
|
}
|
|
72
89
|
|
|
73
90
|
const handleBack = () => {
|
|
74
|
-
// Специальная логика для возврата - очищаем
|
|
91
|
+
// Специальная логика для возврата - очищаем документы для показа Loader при повторном переходе
|
|
75
92
|
console.log(`⬅️ AgreementStep: Возврат с шага ${connectionAgreement.currentStep}`)
|
|
76
93
|
|
|
77
|
-
// Очищаем
|
|
94
|
+
// Очищаем документы, чтобы при повторном переходе вперед показался Loader
|
|
95
|
+
connectionAgreement.setDocument(null)
|
|
78
96
|
connectionAgreement.setSignedDocument(null)
|
|
79
97
|
|
|
80
98
|
if (connectionAgreement.currentStep > 1) {
|
|
@@ -104,9 +122,12 @@ q-step(
|
|
|
104
122
|
label="Назад"
|
|
105
123
|
@click="handleBack"
|
|
106
124
|
)
|
|
125
|
+
|
|
107
126
|
q-btn(
|
|
108
127
|
v-if="isActive"
|
|
109
128
|
color="primary"
|
|
129
|
+
:loading="isSigning"
|
|
130
|
+
:disable="!isDocumentReady"
|
|
110
131
|
label="Подписать"
|
|
111
132
|
@click="handleSign"
|
|
112
133
|
)
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
span.q-ml-xs {{ instance?.is_delegated ? 'Делегирован' : 'Ожидаем делегирования' }}
|
|
56
56
|
|
|
57
57
|
.instruction-footer
|
|
58
|
-
|
|
|
58
|
+
| Мы автоматически проверим домен и активируем установку вашего Цифрового Кооператива
|
|
59
59
|
|
|
60
60
|
//- Навигация
|
|
61
61
|
q-stepper-navigation.q-gutter-sm
|
|
@@ -39,16 +39,46 @@ q-step(
|
|
|
39
39
|
icon="settings"
|
|
40
40
|
:done="isDone"
|
|
41
41
|
)
|
|
42
|
-
.q-pa-md
|
|
42
|
+
.form-step-container.q-pa-md
|
|
43
|
+
|
|
44
|
+
//- Заголовок шага
|
|
45
|
+
.step-header.q-mb-xl
|
|
46
|
+
.text-h6.form-title Настройка параметров кооператива
|
|
47
|
+
.subtitle.text-body2.text-grey-7.q-mt-sm
|
|
48
|
+
| Заполните основные параметры для запуска вашего Цифрового Кооператива
|
|
49
|
+
|
|
50
|
+
//- Форма ввода данных
|
|
43
51
|
CooperativeDataForm(
|
|
44
52
|
@continue="handleContinue"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
q-stepper-navigation.q-gutter-sm
|
|
48
|
-
q-btn(
|
|
49
|
-
color="grey-6"
|
|
50
|
-
flat
|
|
51
|
-
label="Назад"
|
|
52
|
-
@click="handleBack"
|
|
53
|
+
@back="handleBack"
|
|
53
54
|
)
|
|
54
55
|
</template>
|
|
56
|
+
|
|
57
|
+
<style scoped>
|
|
58
|
+
.form-step-container {
|
|
59
|
+
max-width: 900px;
|
|
60
|
+
margin: 0 auto;
|
|
61
|
+
position: relative;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.step-header {
|
|
65
|
+
text-align: center;
|
|
66
|
+
margin-bottom: 2rem;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.form-title {
|
|
70
|
+
font-weight: 700;
|
|
71
|
+
letter-spacing: -0.5px;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Адаптивность */
|
|
75
|
+
@media (max-width: 480px) {
|
|
76
|
+
.form-step-container {
|
|
77
|
+
padding: 1rem;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.step-header {
|
|
81
|
+
margin-bottom: 1.5rem;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
</style>
|
|
@@ -3,12 +3,14 @@ import { computed, withDefaults } from 'vue'
|
|
|
3
3
|
import type { IStepProps } from '../model/types'
|
|
4
4
|
import { TariffSelector, type ITariff } from '../Tariffs'
|
|
5
5
|
import { useConnectionAgreementStore } from 'src/entities/ConnectionAgreement'
|
|
6
|
+
import { useSystemStore } from 'src/entities/System/model'
|
|
6
7
|
|
|
7
8
|
const props = withDefaults(defineProps<IStepProps & {
|
|
8
9
|
selectedTariff?: ITariff | null
|
|
9
10
|
}>(), {})
|
|
10
11
|
|
|
11
12
|
const connectionAgreement = useConnectionAgreementStore()
|
|
13
|
+
const system = useSystemStore()
|
|
12
14
|
|
|
13
15
|
const isActive = computed(() => props.isActive)
|
|
14
16
|
const isDone = computed(() => props.isDone)
|
|
@@ -28,6 +30,12 @@ const handleTariffDeselected = () => {
|
|
|
28
30
|
selectedTariff.value = null
|
|
29
31
|
}
|
|
30
32
|
|
|
33
|
+
const handleBack = () => {
|
|
34
|
+
if (system.info.is_unioned) {
|
|
35
|
+
connectionAgreement.setCurrentStep(0)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
31
39
|
const handleContinue = () => {
|
|
32
40
|
if (canContinue.value && connectionAgreement.currentStep < 5) {
|
|
33
41
|
connectionAgreement.setCurrentStep(connectionAgreement.currentStep + 1)
|
|
@@ -52,6 +60,13 @@ q-step(
|
|
|
52
60
|
)
|
|
53
61
|
|
|
54
62
|
q-stepper-navigation.q-gutter-sm
|
|
63
|
+
q-btn(
|
|
64
|
+
v-if="isActive && system.info.is_unioned"
|
|
65
|
+
color="grey-6"
|
|
66
|
+
flat
|
|
67
|
+
label="Назад"
|
|
68
|
+
@click="handleBack"
|
|
69
|
+
)
|
|
55
70
|
q-btn(
|
|
56
71
|
v-if="isActive"
|
|
57
72
|
color="primary"
|
|
@@ -35,26 +35,61 @@ q-step(
|
|
|
35
35
|
icon="group"
|
|
36
36
|
:done="isDone"
|
|
37
37
|
)
|
|
38
|
-
.q-pa-md
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
.q-mb-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
38
|
+
.union-membership-container.q-pa-md
|
|
39
|
+
|
|
40
|
+
//- Основная информационная карточка
|
|
41
|
+
.membership-info-card.q-mb-xl
|
|
42
|
+
.card-header
|
|
43
|
+
.text-h6.membership-title Членство в Союзе Потребительских Обществ
|
|
44
|
+
.subtitle.text-body2.text-grey-7.q-mt-sm
|
|
45
|
+
| Необходимый шаг для полноценной работы на платформе Кооперативной Экономики
|
|
46
|
+
|
|
47
|
+
//- Что будет сделано
|
|
48
|
+
.membership-benefits.q-mb-lg
|
|
49
|
+
.benefit-section
|
|
50
|
+
.section-title
|
|
51
|
+
q-icon(name="check_circle" size="20px" color="positive").q-mr-sm
|
|
52
|
+
span.text-subtitle1.text-weight-medium Ваш кооператив будет подключен к платформе
|
|
53
|
+
|
|
54
|
+
.benefit-description.text-body2.text-grey-8.q-mt-sm.q-ml-lg
|
|
55
|
+
| Согласно выбранному тарифу членских взносов ваш Цифровой Кооператив получит доступ ко всем сервисам платформы Кооперативной Экономики
|
|
56
|
+
|
|
57
|
+
.benefit-section.q-mt-md
|
|
58
|
+
.section-title
|
|
59
|
+
q-icon(name="security" size="20px" color="primary").q-mr-sm
|
|
60
|
+
span.text-subtitle1.text-weight-medium Документооборот в порядке
|
|
61
|
+
|
|
62
|
+
.benefit-description.text-body2.text-grey-8.q-mt-sm.q-ml-lg
|
|
63
|
+
| Членство в союзе обеспечивает юридическую чистоту всех операций и соответствие требованиям кооперативного законодательства
|
|
64
|
+
|
|
65
|
+
//- Требование членства
|
|
66
|
+
.membership-requirement.q-mt-lg
|
|
67
|
+
.requirement-card
|
|
68
|
+
.requirement-header
|
|
69
|
+
q-icon(name="info" size="24px" color="warning").q-mr-sm
|
|
70
|
+
.text-subtitle1.text-weight-medium Необходимость вступления в союз
|
|
71
|
+
|
|
72
|
+
.requirement-description.text-body2.q-mt-sm
|
|
73
|
+
| Для работы на платформе и обеспечения базового документооборота ваш кооператив должен быть членом Союза Потребительских Обществ. Это обязательное условие для всех участников Кооперативной Экономики.
|
|
74
|
+
|
|
75
|
+
.union-link-section.q-mt-md
|
|
76
|
+
.text-body2.q-mb-sm Для вступления в союз перейдите по официальной ссылке:
|
|
77
|
+
q-btn.union-link-btn(
|
|
78
|
+
v-if="unionLink"
|
|
79
|
+
flat
|
|
80
|
+
color="primary"
|
|
81
|
+
:label="unionLink"
|
|
82
|
+
@click="openUnionLink"
|
|
83
|
+
no-caps
|
|
84
|
+
class="q-mt-sm"
|
|
85
|
+
)
|
|
86
|
+
q-icon(name="open_in_new" size="16px").q-ml-xs
|
|
87
|
+
|
|
88
|
+
span(v-else).text-grey-6.q-mt-sm Ссылка временно недоступна
|
|
89
|
+
|
|
90
|
+
//- Навигация
|
|
91
|
+
|
|
92
|
+
q-stepper-navigation.q-gutter-sm.q-pa-md
|
|
58
93
|
q-btn(
|
|
59
94
|
v-if="isActive"
|
|
60
95
|
color="primary"
|
|
@@ -62,3 +97,205 @@ q-step(
|
|
|
62
97
|
@click="handleContinue"
|
|
63
98
|
)
|
|
64
99
|
</template>
|
|
100
|
+
|
|
101
|
+
<style scoped>
|
|
102
|
+
.union-membership-container {
|
|
103
|
+
max-width: 900px;
|
|
104
|
+
margin: 0 auto;
|
|
105
|
+
position: relative;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* Основная информационная карточка */
|
|
109
|
+
.membership-info-card {
|
|
110
|
+
border-radius: 20px;
|
|
111
|
+
padding: 2.5rem;
|
|
112
|
+
border: 1px solid rgba(0, 0, 0, 0.05);
|
|
113
|
+
box-shadow:
|
|
114
|
+
0 8px 32px rgba(0, 0, 0, 0.08),
|
|
115
|
+
0 2px 8px rgba(0, 0, 0, 0.04);
|
|
116
|
+
position: relative;
|
|
117
|
+
overflow: hidden;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.membership-info-card::before {
|
|
121
|
+
content: '';
|
|
122
|
+
position: absolute;
|
|
123
|
+
top: 0;
|
|
124
|
+
left: 0;
|
|
125
|
+
right: 0;
|
|
126
|
+
height: 4px;
|
|
127
|
+
background: linear-gradient(90deg, var(--q-primary) 0%, var(--q-secondary) 50%, var(--q-accent) 100%);
|
|
128
|
+
background-size: 200% 100%;
|
|
129
|
+
animation: shimmer 4s cubic-bezier(0.25, 0.46, 0.45, 0.94) infinite;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
@keyframes shimmer {
|
|
133
|
+
0% { background-position: 100% 0; }
|
|
134
|
+
100% { background-position: -100% 0; }
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.card-header {
|
|
138
|
+
text-align: center;
|
|
139
|
+
margin-bottom: 2rem;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.membership-title {
|
|
143
|
+
font-weight: 700;
|
|
144
|
+
letter-spacing: -0.5px;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* Секции преимуществ */
|
|
148
|
+
.membership-benefits {
|
|
149
|
+
display: flex;
|
|
150
|
+
flex-direction: column;
|
|
151
|
+
gap: 1rem;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.benefit-section {
|
|
155
|
+
padding: 1.5rem;
|
|
156
|
+
border-radius: 16px;
|
|
157
|
+
background: rgba(25, 118, 210, 0.02);
|
|
158
|
+
border: 1px solid rgba(25, 118, 210, 0.1);
|
|
159
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.benefit-section:hover {
|
|
163
|
+
transform: translateY(-2px);
|
|
164
|
+
box-shadow: 0 8px 25px rgba(25, 118, 210, 0.1);
|
|
165
|
+
background: rgba(25, 118, 210, 0.05);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.section-title {
|
|
169
|
+
display: flex;
|
|
170
|
+
align-items: center;
|
|
171
|
+
margin-bottom: 0.5rem;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.benefit-description {
|
|
175
|
+
line-height: 1.6;
|
|
176
|
+
padding-left: 24px;
|
|
177
|
+
position: relative;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.benefit-description::before {
|
|
181
|
+
content: '';
|
|
182
|
+
position: absolute;
|
|
183
|
+
left: 0;
|
|
184
|
+
top: 0;
|
|
185
|
+
bottom: 0;
|
|
186
|
+
width: 2px;
|
|
187
|
+
background: linear-gradient(180deg, var(--q-primary) 0%, rgba(25, 118, 210, 0.3) 100%);
|
|
188
|
+
border-radius: 1px;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/* Требование членства */
|
|
192
|
+
.membership-requirement {
|
|
193
|
+
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
|
194
|
+
padding-top: 2rem;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.requirement-card {
|
|
198
|
+
padding: 2rem;
|
|
199
|
+
border-radius: 16px;
|
|
200
|
+
background: linear-gradient(135deg, rgba(255, 152, 0, 0.02) 0%, rgba(255, 193, 7, 0.02) 100%);
|
|
201
|
+
border: 1px solid rgba(255, 152, 0, 0.1);
|
|
202
|
+
position: relative;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.requirement-card::before {
|
|
206
|
+
content: '';
|
|
207
|
+
position: absolute;
|
|
208
|
+
top: 0;
|
|
209
|
+
left: 0;
|
|
210
|
+
right: 0;
|
|
211
|
+
height: 3px;
|
|
212
|
+
background: linear-gradient(90deg, #FF9800 0%, #FFC107 50%, #FF9800 100%);
|
|
213
|
+
border-radius: 16px 16px 0 0;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.requirement-header {
|
|
217
|
+
display: flex;
|
|
218
|
+
align-items: center;
|
|
219
|
+
margin-bottom: 1rem;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.requirement-description {
|
|
223
|
+
line-height: 1.6;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/* Секция ссылки на союз */
|
|
227
|
+
.union-link-section {
|
|
228
|
+
padding: 1rem;
|
|
229
|
+
border-radius: 12px;
|
|
230
|
+
border: 1px solid rgba(0, 0, 0, 0.05);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.union-link-btn {
|
|
234
|
+
width: 100%;
|
|
235
|
+
justify-content: center;
|
|
236
|
+
padding: 0.75rem 1rem;
|
|
237
|
+
border-radius: 12px;
|
|
238
|
+
font-weight: 500;
|
|
239
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.union-link-btn:hover {
|
|
243
|
+
transform: translateY(-1px);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/* Адаптивность */
|
|
247
|
+
@media (max-width: 768px) {
|
|
248
|
+
.membership-info-card {
|
|
249
|
+
padding: 2rem;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.benefit-section {
|
|
253
|
+
padding: 1.25rem;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.requirement-card {
|
|
257
|
+
padding: 1.5rem;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.benefit-description {
|
|
261
|
+
padding-left: 20px;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.benefit-description::before {
|
|
265
|
+
width: 1.5px;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
@media (max-width: 480px) {
|
|
270
|
+
.union-membership-container {
|
|
271
|
+
padding: 1rem;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.membership-info-card {
|
|
275
|
+
padding: 1.5rem;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.benefit-section {
|
|
279
|
+
padding: 1rem;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.requirement-card {
|
|
283
|
+
padding: 1.25rem;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.section-title {
|
|
287
|
+
flex-direction: column;
|
|
288
|
+
gap: 0.5rem;
|
|
289
|
+
text-align: center;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.benefit-description {
|
|
293
|
+
padding-left: 0;
|
|
294
|
+
text-align: center;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.benefit-description::before {
|
|
298
|
+
display: none;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
</style>
|
|
@@ -97,7 +97,6 @@ div.tariff-card-container
|
|
|
97
97
|
min-height: 360px; /* Уменьшенная минимальная высота */
|
|
98
98
|
padding: 24px;
|
|
99
99
|
border-radius: 16px;
|
|
100
|
-
background: white;
|
|
101
100
|
border: 2px solid #f0f0f0;
|
|
102
101
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
103
102
|
cursor: pointer;
|
|
@@ -220,7 +219,6 @@ div.tariff-card-container
|
|
|
220
219
|
letter-spacing: -1px;
|
|
221
220
|
background: linear-gradient(135deg, var(--q-accent) 0%, rgba(25, 118, 210, 0.8) 100%);
|
|
222
221
|
-webkit-background-clip: text;
|
|
223
|
-
-webkit-text-fill-color: transparent;
|
|
224
222
|
background-clip: text;
|
|
225
223
|
line-height: 1;
|
|
226
224
|
text-shadow: 0 2px 4px rgba(25, 118, 210, 0.3);
|
|
@@ -29,7 +29,7 @@ q-dialog.cmdk-dialog(
|
|
|
29
29
|
|
|
30
30
|
// Список результатов
|
|
31
31
|
div.cmdk-content(ref="contentRef")
|
|
32
|
-
transition-group
|
|
32
|
+
transition-group(
|
|
33
33
|
name="cmdk-fade",
|
|
34
34
|
tag="div"
|
|
35
35
|
)
|
|
@@ -177,10 +177,6 @@ onUnmounted(() => {
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
.cmdk-results {
|
|
181
|
-
padding: 8px 0;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
180
|
.cmdk-group {
|
|
185
181
|
&:not(:last-child) {
|
|
186
182
|
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
|
@@ -49,6 +49,11 @@ const evaluateCondition = (
|
|
|
49
49
|
}
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
+
// Вычисляем роль пользователя
|
|
53
|
+
const userRole = computed(() =>
|
|
54
|
+
user.isChairman ? 'chairman' : user.isMember ? 'member' : 'user'
|
|
55
|
+
);
|
|
56
|
+
|
|
52
57
|
// Контекст для evaluateCondition и проверки ролей
|
|
53
58
|
const context = computed(() => {
|
|
54
59
|
const isCoop =
|
|
@@ -58,15 +63,9 @@ const context = computed(() => {
|
|
|
58
63
|
user.privateAccount.value.organization_data.type.toUpperCase() ===
|
|
59
64
|
Zeus.OrganizationType.COOP;
|
|
60
65
|
|
|
61
|
-
// Роль берем из computed свойств session
|
|
62
|
-
const userRole = user.isChairman
|
|
63
|
-
? 'chairman'
|
|
64
|
-
: user.isMember
|
|
65
|
-
? 'member'
|
|
66
|
-
: 'user';
|
|
67
66
|
return {
|
|
68
67
|
isCoop,
|
|
69
|
-
userRole,
|
|
68
|
+
userRole: userRole.value,
|
|
70
69
|
userAccount: user.privateAccount.value,
|
|
71
70
|
coopname: info.coopname,
|
|
72
71
|
};
|
|
@@ -148,17 +148,17 @@ const isActive = (workspaceName: string): boolean => {
|
|
|
148
148
|
// workspaceMenus – список рабочих столов из store
|
|
149
149
|
const workspaceMenus = computed(() => desktop.workspaceMenus);
|
|
150
150
|
|
|
151
|
+
// Вычисляем роль пользователя
|
|
152
|
+
const userRole = computed(() =>
|
|
153
|
+
user.isChairman ? 'chairman' : user.isMember ? 'member' : 'user'
|
|
154
|
+
);
|
|
155
|
+
|
|
151
156
|
// Фильтрация по ролям
|
|
152
157
|
const menuWorkspaces = computed(() => {
|
|
153
|
-
const userRole = user.isChairman
|
|
154
|
-
? 'chairman'
|
|
155
|
-
: user.isMember
|
|
156
|
-
? 'member'
|
|
157
|
-
: 'user';
|
|
158
158
|
return workspaceMenus.value
|
|
159
159
|
.filter(
|
|
160
160
|
(item) =>
|
|
161
|
-
item.meta.roles?.includes(userRole) ||
|
|
161
|
+
item.meta.roles?.includes(userRole.value) ||
|
|
162
162
|
item.meta.roles === undefined ||
|
|
163
163
|
item.meta.roles.length === 0
|
|
164
164
|
)
|
|
@@ -174,7 +174,7 @@ if (!shouldRegisterSW) {
|
|
|
174
174
|
// Показываем уведомление пользователю о доступном обновлении
|
|
175
175
|
if ('Notification' in window && Notification.permission === 'granted') {
|
|
176
176
|
new Notification('Обновление доступно', {
|
|
177
|
-
body: '
|
|
177
|
+
body: 'Выпущена новая версия приложения. Нажмите на уведомление, чтобы обновить приложение.',
|
|
178
178
|
icon: '/icons/icon-192x192.png',
|
|
179
179
|
});
|
|
180
180
|
}
|
|
@@ -193,7 +193,7 @@ if (!shouldRegisterSW) {
|
|
|
193
193
|
if ('Notification' in window) {
|
|
194
194
|
if (Notification.permission === 'granted') {
|
|
195
195
|
new Notification('Обновление доступно', {
|
|
196
|
-
body: '
|
|
196
|
+
body: 'Выпущена новая версия приложения. Нажмите на уведомление, чтобы обновить приложение.',
|
|
197
197
|
icon: '/icons/icon-192x192.png',
|
|
198
198
|
requireInteraction: true,
|
|
199
199
|
}).onclick = () => {
|
|
@@ -203,7 +203,7 @@ if (!shouldRegisterSW) {
|
|
|
203
203
|
Notification.requestPermission().then((permission) => {
|
|
204
204
|
if (permission === 'granted') {
|
|
205
205
|
new Notification('Обновление доступно', {
|
|
206
|
-
body: '
|
|
206
|
+
body: 'Выпущена новая версия приложения. Нажмите на уведомление, чтобы обновить приложение.',
|
|
207
207
|
icon: '/icons/icon-192x192.png',
|
|
208
208
|
requireInteraction: true,
|
|
209
209
|
}).onclick = () => {
|