@coopenomics/desktop 2025.11.10-alpha-2 → 2025.11.10-alpha-3

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coopenomics/desktop",
3
- "version": "2025.11.10-alpha-2",
3
+ "version": "2025.11.10-alpha-3",
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.10-alpha-2",
29
- "@coopenomics/notifications": "2025.11.10-alpha-2",
30
- "@coopenomics/sdk": "2025.11.10-alpha-2",
28
+ "@coopenomics/controller": "2025.11.10-alpha-3",
29
+ "@coopenomics/notifications": "2025.11.10-alpha-3",
30
+ "@coopenomics/sdk": "2025.11.10-alpha-3",
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.10-alpha-2",
62
+ "cooptypes": "2025.11.10-alpha-3",
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": "e914a117682b30c65a8fe762148bb579aa50d62d"
126
+ "gitHead": "637950d37f74f959a640d61891ef35d0ace9b858"
127
127
  }
@@ -0,0 +1 @@
1
+ export * from './model'
@@ -0,0 +1,2 @@
1
+ export { useConnectionAgreementStore } from './store'
2
+ export type { ITariff, IConnectionAgreementState } from './types'
@@ -0,0 +1,82 @@
1
+ import { defineStore } from 'pinia'
2
+ import { ref } from 'vue'
3
+ import type { ITariff, IConnectionAgreementState } from './types'
4
+
5
+
6
+ const namespace = 'connection-agreement'
7
+
8
+ export const useConnectionAgreementStore = defineStore(namespace, () => {
9
+ // State
10
+ const currentStep = ref<number>(1)
11
+ const selectedTariff = ref<ITariff | null>(null)
12
+ const isInitialized = ref<boolean>(false)
13
+ const document = ref<any>(null)
14
+ const signedDocument = ref<any>(null)
15
+
16
+ // Methods
17
+ const setCurrentStep = (step: number) => {
18
+ currentStep.value = step
19
+ }
20
+
21
+ const setSelectedTariff = (tariff: ITariff | null) => {
22
+ selectedTariff.value = tariff
23
+ }
24
+
25
+ const setInitialized = (initialized: boolean) => {
26
+ isInitialized.value = initialized
27
+ }
28
+
29
+ const setDocument = (doc: any) => {
30
+ document.value = doc
31
+ }
32
+
33
+ const setSignedDocument = (doc: any) => {
34
+ signedDocument.value = doc
35
+ }
36
+
37
+ const reset = () => {
38
+ currentStep.value = 1
39
+ selectedTariff.value = null
40
+ isInitialized.value = false
41
+ document.value = null
42
+ signedDocument.value = null
43
+ }
44
+
45
+ const initialize = (state: Partial<IConnectionAgreementState>) => {
46
+ if (state.currentStep !== undefined) {
47
+ currentStep.value = state.currentStep
48
+ }
49
+ if (state.selectedTariff !== undefined) {
50
+ selectedTariff.value = state.selectedTariff
51
+ }
52
+ if (state.isInitialized !== undefined) {
53
+ isInitialized.value = state.isInitialized
54
+ }
55
+ if (state.document !== undefined) {
56
+ document.value = state.document
57
+ }
58
+ if (state.signedDocument !== undefined) {
59
+ signedDocument.value = state.signedDocument
60
+ }
61
+ }
62
+
63
+ return {
64
+ // State
65
+ currentStep,
66
+ selectedTariff,
67
+ isInitialized,
68
+ document,
69
+ signedDocument,
70
+
71
+ // Methods
72
+ setCurrentStep,
73
+ setSelectedTariff,
74
+ setInitialized,
75
+ setDocument,
76
+ setSignedDocument,
77
+ reset,
78
+ initialize
79
+ }
80
+ }, {
81
+ persist: true
82
+ })
@@ -0,0 +1,16 @@
1
+ export interface ITariff {
2
+ id: string
3
+ name: string
4
+ description: string
5
+ price: string
6
+ features: string[]
7
+ additionalCosts?: string[]
8
+ }
9
+
10
+ export interface IConnectionAgreementState {
11
+ currentStep: number
12
+ selectedTariff: ITariff | null
13
+ isInitialized: boolean
14
+ document?: any
15
+ signedDocument?: any
16
+ }
@@ -1,5 +1,5 @@
1
1
  <template lang="pug">
2
- Form(:handler-submit="addNow" :is-submitting="isSubmitting" :showCancel="false" :button-cancel-txt="'Отменить'" :button-submit-txt="'Отправить'" @cancel="clear").q-gutter-md
2
+ Form(:handler-submit="addNow" :is-submitting="isSubmitting" :showCancel="false" :button-cancel-txt="'Отменить'" :button-submit-txt="'Продолжить'" @cancel="clear").q-gutter-md
3
3
  //- q-input(standout="bg-teal text-white" label="Имя аккаунта" v-model="data.coopname" :rules="[val => notEmpty(val)]")
4
4
  q-input(standout="bg-teal text-white" hint="domovoy.com или coop.domovoy.com" label="Домен или поддомен для запуска" v-model="data.params.announce" :rules="[val => notEmpty(val), val => isDomain(val)]")
5
5
 
@@ -21,7 +21,7 @@ Form(:handler-submit="addNow" :is-submitting="isSubmitting" :showCancel="false"
21
21
 
22
22
  </template>
23
23
  <script lang="ts" setup>
24
- import { computed, ref } from 'vue';
24
+ import { computed, ref, watch } from 'vue';
25
25
  import { useAddCooperative } from '../model';
26
26
  import { Form } from 'src/shared/ui/Form';
27
27
  import { notEmpty, isDomain } from 'src/shared/lib/utils';
@@ -41,6 +41,10 @@ const props = defineProps({
41
41
  document: {
42
42
  type: Object as () => IDocument,
43
43
  required: true,
44
+ },
45
+ cooperative: {
46
+ type: Object as () => any,
47
+ default: null,
44
48
  }
45
49
  })
46
50
 
@@ -48,17 +52,31 @@ const document = computed(() => props.document)
48
52
 
49
53
  const session = useSessionStore()
50
54
 
55
+ // Функция для извлечения числового значения из IAsset
56
+ const extractNumericValue = (asset: any): string => {
57
+ if (!asset) return ''
58
+ if (typeof asset === 'number') return asset.toString()
59
+ if (typeof asset === 'string') {
60
+ // Извлекаем число из строки типа "1000.0000 RUB" и убираем лишние нули
61
+ const match = asset.match(/^(\d+(?:\.\d+)?)/)
62
+ if (match) {
63
+ return parseFloat(match[1]).toString()
64
+ }
65
+ }
66
+ return ''
67
+ }
68
+
51
69
  const data = ref<RegistratorContract.Actions.RegisterCooperative.IRegisterCooperative>({
52
70
  coopname: session.username,
53
71
  params: {
54
72
  is_cooperative: true,
55
73
  coop_type: 'conscoop',
56
- announce: '',
74
+ announce: props.cooperative?.announce || '',
57
75
  description: '',
58
- initial: '',
59
- minimum: '',
60
- org_initial: '',
61
- org_minimum: ''
76
+ initial: extractNumericValue(props.cooperative?.initial),
77
+ minimum: extractNumericValue(props.cooperative?.minimum),
78
+ org_initial: extractNumericValue(props.cooperative?.org_initial),
79
+ org_minimum: extractNumericValue(props.cooperative?.org_minimum)
62
80
  },
63
81
  username: session.username,
64
82
  document: {
@@ -71,6 +89,17 @@ const data = ref<RegistratorContract.Actions.RegisterCooperative.IRegisterCooper
71
89
  }
72
90
  })
73
91
 
92
+ // Следим за изменениями cooperative и обновляем данные
93
+ watch(() => props.cooperative, (newCooperative) => {
94
+ if (newCooperative) {
95
+ data.value.params.announce = newCooperative.announce || ''
96
+ data.value.params.initial = extractNumericValue(newCooperative.initial)
97
+ data.value.params.minimum = extractNumericValue(newCooperative.minimum)
98
+ data.value.params.org_initial = extractNumericValue(newCooperative.org_initial)
99
+ data.value.params.org_minimum = extractNumericValue(newCooperative.org_minimum)
100
+ }
101
+ }, { immediate: true })
102
+
74
103
  const clear = () => {
75
104
  emit('finish')
76
105
  }
@@ -4,7 +4,8 @@ div.row.q-pa-md
4
4
  div(v-if="system.info.is_providered")
5
5
  ConnectionAgreementStepper(
6
6
  :initial-step="currentStep"
7
- :is-finish="is_finish"
7
+ :is-finish="currentStep >= 5"
8
+ :document="document"
8
9
  :signed-document="signedDocument"
9
10
  :coop="coop"
10
11
  :html="html"
@@ -13,7 +14,9 @@ div.row.q-pa-md
13
14
  :instance-status="instanceStatus"
14
15
  :subscriptions-loading="subscriptionsLoading"
15
16
  :subscriptions-error="subscriptionsError"
17
+ :selected-tariff="connectionAgreement.selectedTariff"
16
18
  @step-change="handleStepChange"
19
+ @clear-signed-document="handleClearSignedDocument"
17
20
  @tariff-selected="handleTariffSelected"
18
21
  @tariff-deselected="handleTariffDeselected"
19
22
  @continue="handleContinue"
@@ -42,6 +45,7 @@ div.row.q-pa-md
42
45
  import { DigitalDocument } from 'src/shared/lib/document';
43
46
  import { useSessionStore } from 'src/entities/Session';
44
47
  import { useSystemStore } from 'src/entities/System/model';
48
+ import { useConnectionAgreementStore } from 'src/entities/ConnectionAgreement';
45
49
  import { computed, ref, onMounted, onUnmounted } from 'vue';
46
50
  import { useLoadCooperatives } from 'src/features/Union/LoadCooperatives';
47
51
  import { useProviderSubscriptions } from 'src/features/Provider';
@@ -52,7 +56,7 @@ import { ColorCard } from 'src/shared/ui';
52
56
 
53
57
  const session = useSessionStore()
54
58
  const system = useSystemStore()
55
- const document = ref(new DigitalDocument())
59
+ const connectionAgreement = useConnectionAgreementStore()
56
60
  const {loadOneCooperative} = useLoadCooperatives()
57
61
  const {
58
62
  domainValid,
@@ -65,39 +69,87 @@ const {
65
69
 
66
70
  const coop = ref()
67
71
 
72
+ // Восстанавливаем документы из persistent store или создаем новые
73
+ const document = computed({
74
+ get: () => {
75
+ if (connectionAgreement.document) {
76
+ // Если есть сохраненный документ, пересоздаем экземпляр DigitalDocument
77
+ const doc = new DigitalDocument()
78
+ if (connectionAgreement.document.data) {
79
+ doc.data = connectionAgreement.document.data
80
+ }
81
+ if (connectionAgreement.document.signedDocument) {
82
+ doc.signedDocument = connectionAgreement.document.signedDocument
83
+ }
84
+ return doc
85
+ }
86
+ return new DigitalDocument()
87
+ },
88
+ set: (value) => connectionAgreement.setDocument(value)
89
+ })
90
+
91
+ const signedDocument = computed({
92
+ get: () => connectionAgreement.signedDocument || document.value?.signedDocument,
93
+ set: (value) => connectionAgreement.setSignedDocument(value)
94
+ })
95
+
68
96
  const html = computed(() => document.value?.data?.html)
69
- const signedDocument = computed(() => document.value?.signedDocument)
70
- const is_finish = ref(false)
71
97
 
72
- // Управление шагом степпера
73
- const currentStep = ref(1)
98
+ // Используем persistent store для управления шагом
99
+ const currentStep = computed({
100
+ get: () => connectionAgreement.currentStep,
101
+ set: (value) => connectionAgreement.setCurrentStep(value)
102
+ })
74
103
 
75
- const handleStepChange = (step: number) => {
104
+ const handleStepChange = async (step: number) => {
76
105
  currentStep.value = step
106
+
107
+ // Если переходим к шагу 2 (соглашение), всегда генерируем документ заново
108
+ if (step === 2) {
109
+ const newDoc = new DigitalDocument()
110
+ await newDoc.generate({
111
+ registry_id: Cooperative.Registry.CoopenomicsAgreement.registry_id,
112
+ coopname: 'voskhod',
113
+ username: session.username,
114
+ })
115
+ document.value = newDoc
116
+ connectionAgreement.setDocument(newDoc)
117
+ }
118
+ }
119
+
120
+ const handleClearSignedDocument = async () => {
121
+ // Очищаем подписанный документ и регенерируем документ при возврате на шаг 2
122
+ signedDocument.value = null
123
+ connectionAgreement.setSignedDocument(null)
124
+
125
+ // Регенерируем документ заново и убеждаемся что он сохраняется
126
+ const newDoc = new DigitalDocument()
127
+ await newDoc.generate({
128
+ registry_id: Cooperative.Registry.CoopenomicsAgreement.registry_id,
129
+ coopname: 'voskhod',
130
+ username: session.username,
131
+ })
132
+ document.value = newDoc
133
+ connectionAgreement.setDocument(newDoc)
77
134
  }
78
135
 
79
136
  const handleTariffSelected = (tariff: any) => {
80
- // Здесь можно сохранить выбранный тариф
137
+ // Сохраняем выбранный тариф в persistent store
138
+ connectionAgreement.setSelectedTariff(tariff)
81
139
  console.log('Selected tariff:', tariff)
82
140
  }
83
141
 
84
142
  const handleTariffDeselected = () => {
85
- // Здесь можно обработать снятие выбора тарифа
143
+ // Очищаем выбранный тариф в persistent store
144
+ connectionAgreement.setSelectedTariff(null)
86
145
  console.log('Tariff deselected')
87
146
  }
88
147
 
89
148
  // Остановка автообновления при размонтировании компонента
90
149
  let stopRefresh: (() => void) | null = null
91
150
 
92
- const handleContinue = async () => {
93
- // Если документ еще не сгенерирован, генерируем его
94
- if (!document.value.data?.html && !coop.value) {
95
- await document.value.generate({
96
- registry_id: Cooperative.Registry.CoopenomicsAgreement.registry_id,
97
- coopname: 'voskhod',
98
- username: session.username,
99
- })
100
- }
151
+ const handleContinue = () => {
152
+ // Документ будет сгенерирован при переходе к шагу 2
101
153
  }
102
154
 
103
155
  const openProviderWebsite = () => {
@@ -109,13 +161,15 @@ const finish = () => {
109
161
  // Эта функция имеет смысл только если провайдер доступен
110
162
  if (!system.info.is_providered) return
111
163
 
112
- is_finish.value = true
113
164
  reload()
114
165
 
115
166
  // Запускаем автообновление подписок каждую минуту
116
167
  if (!stopRefresh) {
117
168
  stopRefresh = startAutoRefresh(60000) // 1 минута
118
169
  }
170
+
171
+ // Сбрасываем persistent состояние после завершения
172
+ connectionAgreement.reset()
119
173
  }
120
174
 
121
175
  //todo loadCooperative by username and check status
@@ -130,22 +184,37 @@ const init = async () => {
130
184
  // Инициализация имеет смысл только если провайдер доступен
131
185
  if (!system.info.is_providered) return
132
186
 
187
+ // Инициализируем persistent store если он еще не инициализирован
188
+ if (!connectionAgreement.isInitialized) {
189
+ connectionAgreement.setInitialized(true)
190
+ }
191
+
133
192
  coop.value = await loadOneCooperative(session.username)
134
193
 
135
194
  if (!coop.value) {
136
- await document.value.generate({
137
- registry_id: Cooperative.Registry.CoopenomicsAgreement.registry_id,
138
- coopname: 'voskhod',
139
- username: session.username,
140
- })
195
+ // Если кооператива нет и мы на шаге 1, документ будет сгенерирован в handleContinue
196
+ // Если пользователь еще не прошел ни одного шага, начинаем с первого
197
+ if (currentStep.value === 1) {
198
+ // Уже на первом шаге
199
+ }
141
200
  } else {
142
- is_finish.value = true
143
- currentStep.value = 4 // Переходим на последний шаг если кооператив уже создан
201
+ // Если кооператив существует, переходим на соответствующий шаг
202
+ // Определяем шаг в зависимости от статуса кооператива и домена
203
+ if (coop.value.status === 'active' && domainValid.value === true) {
204
+ currentStep.value = 5 // Установка и настройка
205
+ } else if (coop.value.status === 'pending') {
206
+ currentStep.value = 5 // Ожидание одобрения (последний шаг)
207
+ } else if (domainValid.value === true) {
208
+ currentStep.value = 5 // Домен валиден, переходим к установке
209
+ } else {
210
+ currentStep.value = 4 // Проверка домена
211
+ }
144
212
  }
145
213
  }
146
214
 
147
215
  const sign = async() => {
148
216
  await document.value.sign(session.username)
217
+ signedDocument.value = document.value.signedDocument
149
218
  }
150
219
 
151
220
  // Lifecycle хуки
@@ -165,9 +234,6 @@ onUnmounted(() => {
165
234
  }
166
235
  })
167
236
 
168
- init()
169
-
170
-
171
237
  /**
172
238
  * Здесь необходимо получить соглашение для подключения и проверить заполнено ли оно.
173
239
  *
@@ -0,0 +1,122 @@
1
+ <template lang="pug">
2
+ q-step(
3
+ :name="4"
4
+ title="Проверка домена"
5
+ icon="domain"
6
+ :done="isDone"
7
+ )
8
+ .q-pa-md
9
+ .text-h6.q-mb-md Проверка домена {{ coop?.announce }}
10
+
11
+ .q-mb-lg
12
+ p.text-body1.q-mb-md
13
+ | Для запуска вашего кооператива необходимо настроить домен. Пожалуйста, следуйте инструкции ниже:
14
+
15
+ q-card(flat bordered).q-pa-md.q-mb-md
16
+ .text-subtitle1.q-mb-sm Инструкция по настройке домена:
17
+ ol.q-pl-md
18
+ li.q-mb-sm Перейдите в панель управления вашим доменом
19
+ li.q-mb-sm Создайте A-запись для домена {{ coop?.announce }}
20
+ li.q-mb-sm Укажите IP-адрес: 51.250.114.13
21
+ li.q-mb-sm Сохраните изменения
22
+ li.q-mb-sm Дождитесь обновления DNS (может занять до 24 часов)
23
+
24
+ .flex.justify-between.items-center.q-mb-md
25
+ span.text-body2 Статус проверки домена:
26
+ q-badge(
27
+ v-if="domainValid === true"
28
+ color="green"
29
+ ) валиден ✓
30
+ q-badge(
31
+ v-if="domainValid === false"
32
+ color="red"
33
+ ) не валиден ✗
34
+ q-badge(
35
+ v-if="domainValid === null && !subscriptionsLoading"
36
+ color="grey"
37
+ ) проверка...
38
+ q-badge(
39
+ v-if="subscriptionsLoading"
40
+ color="blue"
41
+ ) загрузка...
42
+
43
+ .q-mt-md
44
+ div(v-if="domainValid === false").q-mb-md
45
+ q-banner(
46
+ class="text-white bg-orange-500"
47
+ rounded
48
+ )
49
+ template(v-slot:avatar)
50
+ q-icon(name="warning" color="white")
51
+ span Домен еще не настроен или DNS не обновился. Повторите проверку через некоторое время.
52
+
53
+ div(v-if="domainValid === true").q-mb-md
54
+ q-banner(
55
+ class="text-white bg-green-500"
56
+ rounded
57
+ )
58
+ template(v-slot:avatar)
59
+ q-icon(name="check_circle" color="white")
60
+ span Отлично! Домен настроен правильно. Переходим к следующему шагу...
61
+
62
+ .flex.justify-between.q-gutter-sm
63
+ q-btn(
64
+ color="grey-6"
65
+ flat
66
+ label="Назад"
67
+ @click="handleBack"
68
+ )
69
+ q-btn(
70
+ color="primary"
71
+ :disable="domainValid !== true"
72
+ label="Продолжить"
73
+ @click="handleContinue"
74
+ )
75
+ q-btn(
76
+ color="grey-6"
77
+ size="sm"
78
+ flat
79
+ icon="refresh"
80
+ @click="handleReload"
81
+ )
82
+ span обновить
83
+ </template>
84
+
85
+ <script setup lang="ts">
86
+ import { computed, withDefaults } from 'vue'
87
+ import type { IStepProps } from '../model/types'
88
+
89
+ const props = withDefaults(defineProps<IStepProps & {
90
+ coop?: any
91
+ domainValid?: boolean | null
92
+ subscriptionsLoading?: boolean
93
+ subscriptionsError?: string | null
94
+ onReload?: () => void
95
+ onBack?: () => void
96
+ onContinue?: () => void
97
+ }>(), {
98
+ domainValid: null,
99
+ subscriptionsLoading: false,
100
+ subscriptionsError: null
101
+ })
102
+
103
+ const emits = defineEmits<{
104
+ back: []
105
+ continue: []
106
+ reload: []
107
+ }>()
108
+
109
+ const isDone = computed(() => props.isDone)
110
+
111
+ const handleBack = () => {
112
+ emits('back')
113
+ }
114
+
115
+ const handleContinue = () => {
116
+ emits('continue')
117
+ }
118
+
119
+ const handleReload = () => {
120
+ emits('reload')
121
+ }
122
+ </script>
@@ -1,14 +1,19 @@
1
1
  <script setup lang="ts">
2
- import { withDefaults } from 'vue'
2
+ import { computed, withDefaults } from 'vue'
3
3
  import type { IStepProps } from '../model/types'
4
4
  import { AddCooperativeForm } from 'src/features/Union/AddCooperative'
5
5
 
6
- withDefaults(defineProps<IStepProps & {
6
+ const props = withDefaults(defineProps<IStepProps & {
7
+ document?: any
7
8
  signedDocument?: any
9
+ cooperative?: any
8
10
  onFinish?: () => void
9
11
  onBack?: () => void
10
12
  }>(), {})
11
13
 
14
+ // Используем подписанный документ, если он есть, иначе обычный документ
15
+ const documentToUse = computed(() => props.signedDocument || props.document)
16
+
12
17
  const emits = defineEmits<{
13
18
  back: []
14
19
  finish: []
@@ -31,17 +36,16 @@ q-step(
31
36
  :done="isDone"
32
37
  )
33
38
  .q-pa-md
34
- p.text-h6.q-mb-md Предварительная настройка
35
- p.q-mb-md
36
- | Пожалуйста, укажите домен для установки Цифрового Кооператива. Также, укажите суммы вступительных и минимальных паевых взносов для физических лиц, юридических лиц и индивидуальных предпринимателей:
39
+ p.q-pb-md Введите домен для запуска сайта Цифрового Кооператива. Также, укажите суммы вступительных и минимальных паевых взносов для физических лиц, юридических лиц и индивидуальных предпринимателей:
37
40
 
38
41
  AddCooperativeForm(
39
- v-if="signedDocument"
40
- :document="signedDocument"
42
+ v-if="documentToUse"
43
+ :document="documentToUse"
44
+ :cooperative="cooperative"
41
45
  @finish="handleFinish"
42
46
  )
43
47
 
44
- q-stepper-navigation.q-gutter-sm(v-if="signedDocument")
48
+ q-stepper-navigation.q-gutter-sm(v-if="documentToUse")
45
49
  q-btn(
46
50
  color="grey-6"
47
51
  flat
@@ -5,6 +5,7 @@ import { TariffSelector, type ITariff } from '../Tariffs'
5
5
 
6
6
  const props = withDefaults(defineProps<IStepProps & {
7
7
  onContinue?: () => void
8
+ selectedTariff?: ITariff | null
8
9
  }>(), {})
9
10
 
10
11
  const emits = defineEmits<{
@@ -15,7 +16,7 @@ const emits = defineEmits<{
15
16
  const isActive = computed(() => props.isActive)
16
17
  const isDone = computed(() => props.isDone)
17
18
 
18
- const selectedTariff = ref<ITariff | null>(null)
19
+ const selectedTariff = ref<ITariff | null>(props.selectedTariff || null)
19
20
 
20
21
  const canContinue = computed(() => selectedTariff.value !== null)
21
22
 
@@ -47,6 +48,7 @@ q-step(
47
48
 
48
49
  TariffSelector(
49
50
  :disabled="!isActive"
51
+ :selected-tariff="selectedTariff"
50
52
  @tariff-selected="handleTariffSelected"
51
53
  @tariff-deselected="handleTariffDeselected"
52
54
  )
@@ -1,8 +1,82 @@
1
+ <template lang="pug">
2
+ q-step(
3
+ :name="5"
4
+ title="Установка и настройка"
5
+ icon="build"
6
+ :done="isDone"
7
+ )
8
+ .q-pa-md
9
+ .text-h6.q-mb-lg Установка кооператива
10
+
11
+ .q-mb-lg
12
+ p.text-body1.q-mb-md Статус кооператива:
13
+ q-badge(
14
+ v-if="coop?.status == 'pending'"
15
+ color="orange"
16
+ ).q-ml-sm ожидание одобрения
17
+ q-badge(
18
+ v-if="coop?.status == 'active'"
19
+ color="teal"
20
+ ).q-ml-sm активен
21
+ q-badge(
22
+ v-if="coop?.status == 'blocked'"
23
+ color="red"
24
+ ).q-ml-sm заблокирован
25
+
26
+ .q-mb-lg(v-if="coop?.status === 'pending'")
27
+ q-banner(
28
+ class="bg-blue-50 text-blue-800 border-blue-200"
29
+ rounded
30
+ bordered
31
+ )
32
+ template(v-slot:avatar)
33
+ q-icon(name="info" color="blue")
34
+ .text-body2
35
+ | Установка кооператива начнется после того, как союз потребительских обществ примет положительное решение о вашем подключении. Пожалуйста, ожидайте.
36
+
37
+ .q-mb-lg(v-if="coop?.status === 'active'")
38
+ .text-subtitle1.q-mb-md Прогресс установки:
39
+ q-linear-progress(
40
+ :value="installationProgress !== null ? installationProgress / 100 : 0"
41
+ color="primary"
42
+ size="8px"
43
+ rounded
44
+ class="q-mb-sm"
45
+ )
46
+ .text-center.text-caption.q-mb-md
47
+ | {{ installationProgress !== null ? installationProgress : 0 }}% завершено
48
+
49
+ p.text-body2.q-mb-md
50
+ | Когда установка будет завершена, вы получите уведомление и сможете перейти к настройке вашего кооператива.
51
+
52
+ .flex.justify-between.q-gutter-sm.q-mt-lg
53
+ q-btn(
54
+ color="grey-6"
55
+ flat
56
+ label="Назад"
57
+ @click="handleBack"
58
+ )
59
+ q-btn(
60
+ color="primary"
61
+ size="sm"
62
+ icon="refresh"
63
+ @click="handleReload"
64
+ )
65
+ span.q-ml-sm Обновить статус
66
+
67
+ .q-mt-lg(v-if="subscriptionsError")
68
+ q-banner(
69
+ class="text-white bg-red-500"
70
+ rounded
71
+ )
72
+ template(v-slot:avatar)
73
+ q-icon(name="error" color="white")
74
+ span {{ subscriptionsError }}
75
+ </template>
76
+
1
77
  <script setup lang="ts">
2
78
  import { computed, withDefaults } from 'vue'
3
79
  import type { IStepProps } from '../model/types'
4
- import { copyToClipboard } from 'quasar'
5
- import { SuccessAlert } from 'src/shared/api'
6
80
 
7
81
  const props = withDefaults(defineProps<IStepProps & {
8
82
  coop?: any
@@ -35,129 +109,5 @@ const handleBack = () => {
35
109
  const handleReload = () => {
36
110
  emits('reload')
37
111
  }
38
-
39
- const instruction = computed(() => `Создайте A-запись домена ${props.coop?.announce} на IP-адрес: 51.250.114.13`)
40
-
41
- const copy = () => {
42
- copyToClipboard(instruction.value)
43
- .then(() => {
44
- SuccessAlert('Инструкция скопирована в буфер')
45
- })
46
- .catch((e) => {
47
- console.log(e)
48
- })
49
- }
50
112
  </script>
51
113
 
52
- <template lang="pug">
53
- q-step(
54
- :name="4"
55
- title="Установка кооператива"
56
- icon="hourglass_top"
57
- :done="isDone"
58
- )
59
- .q-pa-md
60
- p.text-h6.q-mb-md Кооператив на подключении
61
- p.q-mb-md Статус:
62
- q-badge(
63
- v-if="coop?.status == 'pending'"
64
- color="orange"
65
- ).q-ml-sm ожидание
66
- q-badge(
67
- v-if="coop?.status == 'active'"
68
- color="teal"
69
- ).q-ml-sm активен
70
- q-badge(
71
- v-if="coop?.status == 'blocked'"
72
- color="red"
73
- ).q-ml-sm заблокирован
74
-
75
- q-btn(
76
- color="grey-6"
77
- size="sm"
78
- flat
79
- label="Назад"
80
- @click="handleBack"
81
- )
82
- q-btn(
83
- color="primary"
84
- size="sm"
85
- icon="refresh"
86
- @click="handleReload"
87
- ).q-ml-md
88
- span обновить
89
-
90
- .q-mt-md
91
- p.text-subtitle1 Статус подписки на хостинг:
92
-
93
- div.flex.items-center.q-gutter-sm.q-mt-sm
94
- div
95
- span.text-body2 Валидность домена:
96
- q-badge(
97
- v-if="domainValid === true"
98
- color="green"
99
- ).q-ml-sm валиден
100
- q-badge(
101
- v-if="domainValid === false"
102
- color="red"
103
- ).q-ml-sm не валиден
104
- q-badge(
105
- v-if="domainValid === null && !subscriptionsLoading"
106
- color="grey"
107
- ).q-ml-sm неизвестно
108
- q-badge(
109
- v-if="subscriptionsLoading"
110
- color="blue"
111
- ).q-ml-sm загрузка...
112
-
113
- div
114
- span.text-body2 Прогресс установки:
115
- q-badge(
116
- v-if="installationProgress !== null"
117
- :color="installationProgress === 100 ? 'green' : 'orange'"
118
- ).q-ml-sm {{ installationProgress }}%
119
- q-badge(
120
- v-if="installationProgress === null && !subscriptionsLoading"
121
- color="grey"
122
- ).q-ml-sm неизвестно
123
- q-badge(
124
- v-if="subscriptionsLoading"
125
- color="blue"
126
- ).q-ml-sm загрузка...
127
-
128
- div
129
- span.text-body2 Статус сервера:
130
- q-badge(
131
- v-if="instanceStatus"
132
- :color="instanceStatus === 'active' ? 'green' : instanceStatus === 'error' ? 'red' : 'orange'"
133
- ).q-ml-sm {{ instanceStatus }}
134
- q-badge(
135
- v-if="!instanceStatus && !subscriptionsLoading"
136
- color="grey"
137
- ).q-ml-sm неизвестно
138
- q-badge(
139
- v-if="subscriptionsLoading"
140
- color="blue"
141
- ).q-ml-sm загрузка...
142
-
143
- .q-mt-md
144
- div(
145
- v-if="subscriptionsError"
146
- ).q-mb-md
147
- q-banner(
148
- :class="'text-white bg-red-500'"
149
- rounded
150
- )
151
- template(v-slot:avatar)
152
- q-icon(name="error" color="white")
153
- span {{ subscriptionsError }}
154
-
155
- p.q-mt-md
156
- | Пожалуйста, перешлите инструкцию ниже вашему техническому специалисту. После её выполнения, мы автоматически выполним запуск. Далее, Вам необходимо завершить установку уже на Вашем сайте следуя инструкциям, представленным там.
157
-
158
- q-card(flat bordered).q-pa-sm.q-mt-md
159
- p.text-bold Инструкция
160
- div.flex.justify-between
161
- span {{ instruction }}
162
- q-btn(size="sm" icon="fas fa-copy" flat @click="copy")
163
- </template>
@@ -1,4 +1,5 @@
1
1
  export { default as IntroStep } from './IntroStep.vue'
2
2
  export { default as AgreementStep } from './AgreementStep.vue'
3
3
  export { default as FormStep } from './FormStep.vue'
4
+ export { default as DomainValidationStep } from './DomainValidationStep.vue'
4
5
  export { default as WaitingStep } from './WaitingStep.vue'
@@ -24,8 +24,9 @@ const availableTariffs: ITariff[] = [
24
24
  }
25
25
  ]
26
26
 
27
- defineProps<{
27
+ const props = defineProps<{
28
28
  disabled?: boolean
29
+ selectedTariff?: ITariff | null
29
30
  }>()
30
31
 
31
32
  const emits = defineEmits<{
@@ -33,9 +34,9 @@ const emits = defineEmits<{
33
34
  tariffDeselected: []
34
35
  }>()
35
36
 
36
- const selectedTariffId = ref<string>('')
37
+ const selectedTariffId = ref<string>(props.selectedTariff?.id || '')
37
38
 
38
- const selectedTariff = computed(() => {
39
+ const currentSelectedTariff = computed(() => {
39
40
  return availableTariffs.find(tariff => tariff.id === selectedTariffId.value)
40
41
  })
41
42
 
@@ -56,7 +57,7 @@ const handleTariffDeselect = (tariffId: string) => {
56
57
 
57
58
  // Экспортируем для использования в родительском компоненте
58
59
  defineExpose({
59
- selectedTariff,
60
+ currentSelectedTariff,
60
61
  hasSelection: computed(() => !!selectedTariffId.value)
61
62
  })
62
63
  </script>
@@ -1,10 +1,11 @@
1
1
  <script setup lang="ts">
2
2
  import { ref } from 'vue'
3
- import { IntroStep, AgreementStep, FormStep, WaitingStep } from '../Steps/index'
3
+ import { IntroStep, AgreementStep, FormStep, DomainValidationStep, WaitingStep } from '../Steps/index'
4
4
 
5
5
  const props = defineProps<{
6
6
  initialStep?: number
7
7
  isFinish: boolean
8
+ document?: any
8
9
  signedDocument: any
9
10
  coop: any
10
11
  html?: string
@@ -13,6 +14,7 @@ const props = defineProps<{
13
14
  instanceStatus?: string | null
14
15
  subscriptionsLoading?: boolean
15
16
  subscriptionsError?: string | null
17
+ selectedTariff?: any
16
18
  }>()
17
19
 
18
20
  const emits = defineEmits<{
@@ -23,13 +25,14 @@ const emits = defineEmits<{
23
25
  sign: []
24
26
  finish: []
25
27
  reload: []
28
+ clearSignedDocument: []
26
29
  }>()
27
30
 
28
31
  const currentStep = ref(props.initialStep || 1)
29
32
 
30
33
  // Управление шагами
31
34
  const goToNext = () => {
32
- if (currentStep.value < 4) {
35
+ if (currentStep.value < 5) {
33
36
  currentStep.value++
34
37
  emits('stepChange', currentStep.value)
35
38
  }
@@ -47,6 +50,14 @@ const handleContinue = () => {
47
50
  emits('continue')
48
51
  }
49
52
 
53
+ const handleBack = () => {
54
+ goToPrev()
55
+ // Если возвращаемся на шаг 2 (соглашение), очищаем подписанный документ
56
+ if (currentStep.value === 2) {
57
+ emits('clearSignedDocument')
58
+ }
59
+ }
60
+
50
61
  const handleSign = () => {
51
62
  goToNext()
52
63
  emits('sign')
@@ -84,6 +95,7 @@ div
84
95
  :current-step="currentStep"
85
96
  :is-active="currentStep === 1"
86
97
  :is-done="currentStep > 1"
98
+ :selected-tariff="selectedTariff"
87
99
  @continue="handleContinue"
88
100
  @tariff-selected="handleTariffSelected"
89
101
  @tariff-deselected="handleTariffDeselected"
@@ -94,7 +106,7 @@ div
94
106
  :is-active="currentStep === 2"
95
107
  :is-done="currentStep > 2"
96
108
  :html="html"
97
- @back="goToPrev"
109
+ @back="handleBack"
98
110
  @sign="handleSign"
99
111
  )
100
112
 
@@ -102,14 +114,29 @@ div
102
114
  :current-step="currentStep"
103
115
  :is-active="currentStep === 3"
104
116
  :is-done="currentStep > 3"
117
+ :document="document"
105
118
  :signed-document="signedDocument"
119
+ :cooperative="coop"
106
120
  @back="goToPrev"
107
121
  @finish="handleFinish"
108
122
  )
109
123
 
110
- WaitingStep(
124
+ DomainValidationStep(
111
125
  :current-step="currentStep"
112
126
  :is-active="currentStep === 4"
127
+ :is-done="currentStep > 4"
128
+ :coop="coop"
129
+ :domain-valid="domainValid"
130
+ :subscriptions-loading="subscriptionsLoading"
131
+ :subscriptions-error="subscriptionsError"
132
+ @back="goToPrev"
133
+ @continue="goToNext"
134
+ @reload="handleReload"
135
+ )
136
+
137
+ WaitingStep(
138
+ :current-step="currentStep"
139
+ :is-active="currentStep === 5"
113
140
  :is-done="false"
114
141
  :coop="coop"
115
142
  :domain-valid="domainValid"