@coopenomics/desktop 2.2.8 → 2.2.10

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 (32) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/Env-testnet.ts +12 -0
  3. package/package.json +5 -5
  4. package/src/boot/init-stores.ts +8 -2
  5. package/src/desktops/User/model/index.ts +11 -10
  6. package/src/entities/Account/api/index.ts +11 -2
  7. package/src/entities/Account/model/store.ts +15 -5
  8. package/src/entities/Account/types/index.ts +9 -1
  9. package/src/entities/Session/model/store.ts +2 -3
  10. package/src/features/Account/UpdateAccount/api/index.ts +14 -0
  11. package/src/features/Account/UpdateAccount/index.ts +1 -0
  12. package/src/features/Account/UpdateAccount/model/index.ts +16 -0
  13. package/src/features/Branch/SelectBranch/ui/SelectBranchOverlay.vue +3 -2
  14. package/src/features/PaymentMethod/UpdateBankAccount/api/index.ts +1 -0
  15. package/src/features/PaymentMethod/UpdateBankAccount/model/index.ts +11 -4
  16. package/src/features/Request/CreateChildOrder/ui/CreateChildOrderButton/CreateChildOrderButton.vue +1 -1
  17. package/src/features/User/AddUser/ui/AddUserDialog/AddUserDialog.vue +3 -0
  18. package/src/features/User/Logout/model/index.ts +3 -3
  19. package/src/pages/Cooperative/ListOfBranches/ui/ListOfBranchesPage.vue +2 -4
  20. package/src/pages/Marketplace/OfferPage/ui/OfferPage.vue +2 -2
  21. package/src/shared/lib/composables/useEditableData.ts +1 -1
  22. package/src/shared/lib/consts/workspaces/index.ts +1 -0
  23. package/src/shared/ui/EditableEntrepreneurCard/EditableEntrepreneurCard.vue +170 -0
  24. package/src/shared/ui/EditableEntrepreneurCard/index.ts +1 -0
  25. package/src/shared/ui/EditableIndividualCard/EditableIndividualCard.vue +203 -0
  26. package/src/shared/ui/EditableIndividualCard/index.ts +1 -0
  27. package/src/shared/ui/EditableOrganizationCard/EditableOrganizationCard.vue +215 -0
  28. package/src/shared/ui/EditableOrganizationCard/index.ts +1 -0
  29. package/src/shared/ui/UserDataForm/OrganizationDataForm/OrganizationDataForm.vue +1 -0
  30. package/src/widgets/Cooperative/Participants/ListOfParticipants/ui/ListOfParticipantsWidget.vue +154 -71
  31. package/src/widgets/IndividualCard/ui/IndividualCard.vue +23 -23
  32. package/src/widgets/Request/RequestCard/RequestCard.vue +3 -3
@@ -0,0 +1,203 @@
1
+ <template lang="pug">
2
+ q-form(ref="form" v-if="data")
3
+ q-input(
4
+ dense
5
+ v-model="data.email"
6
+ standout="bg-teal text-white"
7
+ label="Email"
8
+ :readonly="readonly"
9
+ :rules="[val => validEmail(val)]"
10
+ autocomplete="off"
11
+ )
12
+ q-input(
13
+ dense
14
+ v-model="data.first_name"
15
+ standout="bg-teal text-white"
16
+ label="Имя"
17
+ :readonly="readonly"
18
+ :rules="[val => notEmpty(val)]"
19
+ autocomplete="off"
20
+ )
21
+
22
+ q-input(
23
+ dense
24
+ v-model="data.middle_name"
25
+ standout="bg-teal text-white"
26
+ label="Отчество"
27
+ :readonly="readonly"
28
+ :rules="[val => validatePersonalName(val)]"
29
+ autocomplete="off"
30
+ )
31
+
32
+ q-input(
33
+ dense
34
+ v-model="data.last_name"
35
+ standout="bg-teal text-white"
36
+ label="Фамилия"
37
+ :readonly="readonly"
38
+ :rules="[val => notEmpty(val), val => validatePersonalName(val)]"
39
+ autocomplete="off"
40
+ )
41
+
42
+ q-input(
43
+ dense
44
+ v-model="data.birthdate"
45
+ standout="bg-teal text-white"
46
+ mask="date"
47
+ label="Дата рождения"
48
+ placeholder="Формат: год/месяц/день"
49
+ :readonly="readonly"
50
+ :rules="['date', val => notEmpty(val)]"
51
+ autocomplete="off"
52
+ )
53
+ template(v-slot:append)
54
+ q-icon(name="event" class="cursor-pointer" v-if="!readonly")
55
+ q-popup-proxy(cover transition-show="scale" transition-hide="scale")
56
+ q-date(v-model="data.birthdate")
57
+ .row.items-center.justify-end
58
+ q-btn(v-close-popup label="Закрыть" color="primary" flat)
59
+
60
+ q-input(
61
+ dense
62
+ v-model="data.phone"
63
+ standout="bg-teal text-white"
64
+ label="Телефон"
65
+ :readonly="readonly"
66
+ :rules="[val => notEmpty(val)]"
67
+ autocomplete="off"
68
+ )
69
+
70
+ div(v-if="data.passport")
71
+ q-input(
72
+ dense
73
+ v-model="data.passport.code"
74
+ standout="bg-teal text-white"
75
+ label="Код подразделения"
76
+ mask="###-###"
77
+ :readonly="readonly"
78
+ :rules="[val => notEmpty(val), val => val.length === 7 || 'Код подразделения состоит из 6 цифр и тире (xxx-xxx)']"
79
+ autocomplete="off"
80
+ )
81
+
82
+ q-input(
83
+ dense
84
+ :model-value="data.passport.series"
85
+ @update:model-value="val => data.passport.series = Number(val)"
86
+ standout="bg-teal text-white"
87
+ label="Серия паспорта"
88
+ mask="####"
89
+ type="text"
90
+ :readonly="readonly"
91
+ :rules="[val => notEmpty(val), val => String(val).length === 4 || 'Серия должна состоять из 4 цифр']"
92
+ autocomplete="off"
93
+ )
94
+
95
+ q-input(
96
+ dense
97
+ :model-value="data.passport.number"
98
+ @update:model-value="val => data.passport.number = Number(val)"
99
+ standout="bg-teal text-white"
100
+ label="Номер паспорта"
101
+ mask="######"
102
+ type="text"
103
+ :readonly="readonly"
104
+ :rules="[val => notEmpty(val), val => String(val).length === 6 || 'Номер паспорта должен состоять из 6 цифр']"
105
+ autocomplete="off"
106
+ )
107
+
108
+
109
+
110
+ q-input(
111
+ dense
112
+ v-model="data.passport.issued_at"
113
+ standout="bg-teal text-white"
114
+ mask="date"
115
+ label="Дата выдачи"
116
+ :readonly="readonly"
117
+ :rules="['date', val => notEmpty(val)]"
118
+ autocomplete="off"
119
+ )
120
+ template(v-slot:append)
121
+ q-icon(name="event" class="cursor-pointer" v-if="!readonly")
122
+ q-popup-proxy(cover transition-show="scale" transition-hide="scale")
123
+ q-date(v-model="data.passport.issued_at")
124
+ .row.items-center.justify-end
125
+ q-btn(v-close-popup label="Закрыть" color="primary" flat)
126
+
127
+ q-input(
128
+ dense
129
+ v-model="data.passport.issued_by"
130
+ standout="bg-teal text-white"
131
+ label="Кем выдан"
132
+ :readonly="readonly"
133
+ :rules="[val => notEmpty(val)]"
134
+ autocomplete="off"
135
+ )
136
+
137
+ q-input(
138
+ dense
139
+ v-model="data.full_address"
140
+ standout="bg-teal text-white"
141
+ label="Адрес регистрации"
142
+ :readonly="readonly"
143
+ :rules="[val => notEmpty(val)]"
144
+ autocomplete="off"
145
+ )
146
+
147
+ EditableActions(
148
+ v-if="!readonly"
149
+ :isEditing="isEditing"
150
+ :isDisabled="isDisabled"
151
+ @save="saveChanges"
152
+ @cancel="cancelChanges"
153
+ )
154
+ </template>
155
+
156
+ <script lang="ts" setup>
157
+ import { ref } from 'vue';
158
+ import { useEditableData } from 'src/shared/lib/composables/useEditableData';
159
+ import { validEmail } from 'src/shared/lib/utils/validEmailRule';
160
+ import { validatePersonalName, notEmpty } from 'src/shared/lib/utils';
161
+ import { failAlert, SuccessAlert } from 'src/shared/api';
162
+ import { type IUpdateAccountInput, useUpdateAccount } from 'src/features/Account/UpdateAccount/model';
163
+ import { EditableActions } from 'src/shared/ui/EditableActions';
164
+ import { type IIndividualData } from 'src/entities/Account/types';
165
+
166
+ const { updateAccount } = useUpdateAccount()
167
+
168
+ const props = defineProps({
169
+ participantData: {
170
+ type: Object as () => IIndividualData,
171
+ required: true
172
+ },
173
+ readonly: {
174
+ type: Boolean,
175
+ default: false
176
+ }
177
+ });
178
+
179
+ const localParticipantData = ref(props.participantData);
180
+ const form = ref();
181
+ const emit = defineEmits(['update']);
182
+
183
+ const handleSave = async () => {
184
+ try {
185
+ const account_data: IUpdateAccountInput = {
186
+ username: props.participantData.username,
187
+ individual_data: data.value,
188
+ }
189
+ await updateAccount(account_data);
190
+ emit('update', JSON.parse(JSON.stringify(data.value)))
191
+ SuccessAlert('Данные аккаунта обновлены')
192
+ } catch (e: any) {
193
+ failAlert(e);
194
+ }
195
+ };
196
+
197
+ const { editableData: data, isEditing, isDisabled, saveChanges, cancelChanges } = useEditableData(
198
+ localParticipantData.value,
199
+ handleSave,
200
+ form
201
+ );
202
+ </script>
203
+
@@ -0,0 +1 @@
1
+ export {default as EditableIndividualCard} from './EditableIndividualCard.vue'
@@ -0,0 +1,215 @@
1
+ <template lang="pug">
2
+ q-form(ref="form" v-if="data")
3
+ q-select(
4
+ dense
5
+ v-model="data.type"
6
+ standout="bg-teal text-white"
7
+ label="Тип организации"
8
+ :options="[{ label: 'Потребительский Кооператив', value: 'coop' }, { label: 'Производственный Кооператив', value: 'prodcoop' }, { label: 'ООО', value: 'ooo' }]"
9
+ emit-value
10
+ map-options
11
+ :rules="[val => notEmpty(val)]"
12
+ :readonly="readonly"
13
+ )
14
+
15
+ q-input(
16
+ dense
17
+ v-model="data.short_name"
18
+ standout="bg-teal text-white"
19
+ label="Краткое наименование"
20
+ :rules="[val => notEmpty(val)]"
21
+ :readonly="readonly"
22
+ autocomplete="off"
23
+ )
24
+ q-input(
25
+ dense
26
+ v-model="data.full_name"
27
+ standout="bg-teal text-white"
28
+ label="Полное наименование"
29
+ :rules="[val => notEmpty(val)]"
30
+ :readonly="readonly"
31
+ autocomplete="off"
32
+ )
33
+
34
+ q-input(
35
+ dense
36
+ v-model="data.represented_by.last_name"
37
+ standout="bg-teal text-white"
38
+ label="Фамилия представителя"
39
+ :rules="[val => notEmpty(val), val => validatePersonalName(val)]"
40
+ :readonly="readonly"
41
+ autocomplete="off"
42
+ )
43
+ q-input(
44
+ dense
45
+ v-model="data.represented_by.first_name"
46
+ standout="bg-teal text-white"
47
+ label="Имя представителя"
48
+ :rules="[val => notEmpty(val), val => validatePersonalName(val)]"
49
+ :readonly="readonly"
50
+ autocomplete="off"
51
+ )
52
+ q-input(
53
+ dense
54
+ v-model="data.represented_by.middle_name"
55
+ standout="bg-teal text-white"
56
+ label="Отчество представителя"
57
+ :rules="[val => validatePersonalName(val)]"
58
+ :readonly="readonly"
59
+ autocomplete="off"
60
+ )
61
+ q-input(
62
+ dense
63
+ v-model="data.represented_by.based_on"
64
+ standout="bg-teal text-white"
65
+ label="На основании"
66
+ :rules="[val => notEmpty(val)]"
67
+ :readonly="readonly"
68
+ autocomplete="off"
69
+ )
70
+ q-input(
71
+ dense
72
+ v-model="data.represented_by.position"
73
+ standout="bg-teal text-white"
74
+ label="Должность представителя"
75
+ :rules="[val => notEmpty(val)]"
76
+ :readonly="readonly"
77
+ autocomplete="off"
78
+ )
79
+
80
+ q-input(
81
+ dense
82
+ v-model="data.phone"
83
+ standout="bg-teal text-white"
84
+ label="Телефон"
85
+ mask="+7 (###) ###-##-##"
86
+ fill-mask
87
+ :rules="[val => notEmpty(val), val => notEmptyPhone(val)]"
88
+ :readonly="readonly"
89
+ autocomplete="off"
90
+ )
91
+
92
+ q-input(
93
+ dense
94
+ v-model="data.country"
95
+ standout="bg-teal text-white"
96
+ label="Страна"
97
+ :rules="[val => notEmpty(val)]"
98
+ :readonly="readonly"
99
+ autocomplete="off"
100
+ )
101
+ q-input(
102
+ dense
103
+ v-model="data.city"
104
+ standout="bg-teal text-white"
105
+ label="Город"
106
+ :rules="[val => notEmpty(val)]"
107
+ :readonly="readonly"
108
+ autocomplete="off"
109
+ )
110
+ q-input(
111
+ dense
112
+ v-model="data.full_address"
113
+ standout="bg-teal text-white"
114
+ label="Юридический адрес"
115
+ :rules="[val => notEmpty(val)]"
116
+ :readonly="readonly"
117
+ autocomplete="off"
118
+ )
119
+ q-input(
120
+ dense
121
+ v-model="data.fact_address"
122
+ standout="bg-teal text-white"
123
+ label="Фактический адрес"
124
+ :rules="[val => notEmpty(val)]"
125
+ :readonly="readonly"
126
+ autocomplete="off"
127
+ )
128
+
129
+ q-input(
130
+ dense
131
+ v-model="data.details.inn"
132
+ standout="bg-teal text-white"
133
+ mask="############"
134
+ label="ИНН"
135
+ :rules="[val => notEmpty(val), val => (val.length === 10 || val.length === 12) || 'ИНН должен содержать 10 или 12 цифр']"
136
+ :readonly="readonly"
137
+ autocomplete="off"
138
+ )
139
+ q-input(
140
+ dense
141
+ v-model="data.details.ogrn"
142
+ standout="bg-teal text-white"
143
+ mask="###############"
144
+ label="ОГРН"
145
+ :rules="[val => notEmpty(val), val => (val.length === 13 || val.length === 15) || 'ОГРН должен содержать 13 или 15 цифр']"
146
+ :readonly="readonly"
147
+ autocomplete="off"
148
+ )
149
+ q-input(
150
+ dense
151
+ v-model="data.details.kpp"
152
+ standout="bg-teal text-white"
153
+ mask="#########"
154
+ label="КПП"
155
+ :rules="[val => notEmpty(val), val => val.length === 9 || 'КПП должен содержать 9 цифр']"
156
+ :readonly="readonly"
157
+ autocomplete="off"
158
+ )
159
+
160
+ EditableActions(
161
+ v-if="!readonly"
162
+ :isEditing="isEditing"
163
+ :isDisabled="isDisabled"
164
+ @save="saveChanges"
165
+ @cancel="cancelChanges"
166
+ )
167
+ </template>
168
+
169
+ <script lang="ts" setup>
170
+ import { ref } from 'vue';
171
+ import { useEditableData } from 'src/shared/lib/composables/useEditableData';
172
+ import { notEmpty, notEmptyPhone, validatePersonalName } from 'src/shared/lib/utils';
173
+ import { failAlert, SuccessAlert } from 'src/shared/api';
174
+ import { EditableActions } from 'src/shared/ui/EditableActions';
175
+ import { type IUpdateAccountInput, useUpdateAccount } from 'src/features/Account/UpdateAccount/model';
176
+ import { type IOrganizationData } from 'src/entities/Account/types';
177
+
178
+ const emit = defineEmits(['update']);
179
+ const { updateAccount } = useUpdateAccount();
180
+
181
+ const props = defineProps({
182
+ participantData: {
183
+ type: Object as () => IOrganizationData,
184
+ required: true
185
+ },
186
+ readonly: {
187
+ type: Boolean,
188
+ default: false
189
+ }
190
+ });
191
+
192
+ const localOrganizationData = ref(props.participantData);
193
+ const form = ref();
194
+
195
+ const handleSave = async () => {
196
+ try {
197
+ const account_data: IUpdateAccountInput = {
198
+ username: props.participantData.username,
199
+ organization_data: data.value,
200
+ };
201
+ await updateAccount(account_data);
202
+ emit('update', JSON.parse(JSON.stringify(data.value)));
203
+ SuccessAlert('Данные аккаунта обновлены');
204
+ } catch (e) {
205
+ console.log(e);
206
+ failAlert(e);
207
+ }
208
+ };
209
+ const { editableData: data, isEditing, isDisabled, saveChanges, cancelChanges } = useEditableData(
210
+ localOrganizationData.value,
211
+ handleSave,
212
+ form
213
+ );
214
+ </script>
215
+
@@ -0,0 +1 @@
1
+ export {default as EditableOrganizationCard} from './EditableOrganizationCard.vue'
@@ -7,6 +7,7 @@ div(v-if="userData.organization_data").q-gutter-sm.q-mt-md
7
7
  :options="[{ label: 'Потребительский Кооператив', value: 'coop' }, { label: 'Производственный Кооператив', value: 'prodcoop' }, { label: 'ООО', value: 'ooo' }]"
8
8
  emit-value
9
9
  map-options).q-mb-md
10
+
10
11
  q-input(v-model="userData.organization_data.short_name" standout="bg-teal text-white" hint="ПК Ромашка" label="Краткое наименование организации" :rules="[val => notEmpty(val)]" autocomplete="off")
11
12
  q-input(v-model="userData.organization_data.full_name" standout="bg-teal text-white" hint="Потребительский Кооператив 'Ромашка'" label="Полное наименование организации" :rules="[val => notEmpty(val)]" autocomplete="off")
12
13
  q-input(v-model="userData.organization_data.represented_by.last_name" standout="bg-teal text-white" label="Фамилия представителя" hint="" :rules="[val => notEmpty(val), val => validatePersonalName(val)]" autocomplete="off")
@@ -1,10 +1,10 @@
1
1
  <template lang="pug">
2
+
2
3
  q-table(
3
- ref="tableRef" v-model:expanded="expanded"
4
+ ref="tableRef"
4
5
  flat
5
- :rows="participants.results"
6
+ :rows="accountStore.accounts.items"
6
7
  :columns="columns"
7
- :table-colspan="9"
8
8
  row-key="username"
9
9
  :pagination="pagination"
10
10
  virtual-scroll
@@ -15,12 +15,10 @@ q-table(
15
15
  ).full-height
16
16
  template(#top)
17
17
  slot(name="top")
18
-
18
+
19
19
  template(#header="props")
20
-
21
20
  q-tr(:props="props")
22
21
  q-th(auto-width)
23
-
24
22
  q-th(
25
23
  v-for="col in props.cols"
26
24
  :key="col.name"
@@ -28,76 +26,161 @@ q-table(
28
26
  ) {{ col.label }}
29
27
 
30
28
  template(#body="props")
29
+
31
30
  q-tr(:key="`m_${props.row.username}`" :props="props")
32
31
  q-td(auto-width)
33
- // q-toggle(v-model="props.expand" checked-icon="fas fa-chevron-circle-left" unchecked-icon="fas fa-chevron-circle-right" )
34
- q-btn(size="sm" color="primary" round dense :icon="props.expand ? 'remove' : 'add'" @click="props.expand = !props.expand")
32
+ q-btn(
33
+ size="sm"
34
+ color="primary"
35
+ round
36
+ dense
37
+ :icon="expanded.get(props.row.username) ? 'remove' : 'add'"
38
+ @click="toggleExpand(props.row.username)"
39
+ )
40
+
41
+ q-td {{ getName(props.row) }}
42
+ q-td {{ props.row.private_account.type === AccountTypes.Individual ? 'физ. лицо' : (props.row.private_account.type === AccountTypes.Organization ? 'юр. лицо' : (props.row.private_account.type === AccountTypes.Entrepreneur ? 'инд. предприниматель' : 'неизвестно')) }}
35
43
  q-td {{ props.row.username }}
36
- q-td {{ props.row.private_data?.last_name }}
37
- q-td {{ props.row.private_data?.first_name }}
38
- q-td {{ props.row.private_data?.middle_name }}
39
- q-td {{ props.row.private_data?.phone }}
40
- q-td {{ props.row.private_data?.email }}
41
- q-td {{ moment(props.row.private_data?.birthdate).format('DD.MM.YY') }}
42
- q-td {{ moment(props.row.private_data?._created_at).format('DD.MM.YY HH:mm:ss') }}
43
-
44
-
45
- q-tr(v-show="props.expand" :key="`e_${props.row.username}`" :props="props" class="q-virtual-scroll--with-prev")
46
- q-td(colspan="100%")
47
- slot(:expand="props.expand" :receiver="props.row.username")
48
-
44
+ q-td {{ moment(props.row.blockchain_account?.created).format('DD.MM.YY HH:mm:ss') }}
45
+
46
+ q-tr(v-if="expanded.get(props.row.username)" :key="`e_${props.row.username}`" :props="props" class="q-virtual-scroll--with-prev")
47
+ q-td(colspan="100%" style="padding: 0 !important;")
48
+ q-tabs(
49
+ v-model="currentTab[props.row.username]"
50
+ align="justify"
51
+ stretch
52
+ dense
53
+ indicator-color="lime"
54
+ )
55
+ q-tab(name="info" label="Данные" class="bg-primary text-white")
56
+ q-tab(name="document" label="Документы" class="bg-primary text-white")
57
+
58
+ q-tab-panels(v-model="currentTab[props.row.username]" animated)
59
+ q-tab-panel(name="info")
60
+ component(:is="useComponent(props.row)" :participantData="usePrivateData(props.row)" @update="newData => update(props.row, newData)")
61
+
62
+ q-tab-panel(name="document")
63
+ slot(:expand="expanded.get(props.row.username)" :receiver="props.row.username")
64
+
49
65
  </template>
50
-
51
66
  <script setup lang="ts">
52
- import { ref } from 'vue'
53
- import { Notify } from 'quasar'
54
-
55
- import { sendGET } from 'src/shared/api';
56
- const participants = ref({ results: [] })
57
- const onLoading = ref(false)
58
-
59
- import moment from 'moment-with-locales-es6'
60
-
61
- const loadParticipants = async () => {
62
- try {
63
- onLoading.value = true
64
-
65
- participants.value = await sendGET('/v1/users', {
66
- limit: 100
67
- })
68
-
69
- onLoading.value = false
70
- } catch (e: any) {
71
- onLoading.value = false
72
- Notify.create({
73
- message: e.message,
74
- type: 'negative',
75
- })
67
+ import { ref, reactive } from 'vue'
68
+ import { Notify } from 'quasar'
69
+ import { EditableEntrepreneurCard } from 'src/shared/ui/EditableEntrepreneurCard';
70
+ import { EditableIndividualCard } from 'src/shared/ui/EditableIndividualCard';
71
+ import { EditableOrganizationCard } from 'src/shared/ui/EditableOrganizationCard';
72
+ import { useAccountStore } from 'src/entities/Account/model';
73
+ import moment from 'moment-with-locales-es6'
74
+ import { AccountTypes, type IAccount, type IIndividualData, type IOrganizationData, type IEntrepreneurData } from 'src/entities/Account/types';
75
+
76
+ const accountStore = useAccountStore()
77
+
78
+ const onLoading = ref(false)
79
+
80
+ const update = (
81
+ account: IAccount,
82
+ newData: IIndividualData | IOrganizationData | IEntrepreneurData
83
+ ) => {
84
+
85
+ if (account.private_account?.type === AccountTypes.Individual) {
86
+ const individual = newData as IIndividualData;
87
+ account.private_account.individual_data = {
88
+ ...individual,
89
+ passport: individual.passport ?? undefined, // заменяет null на undefined
90
+ };
91
+ } else if (account.private_account?.type === AccountTypes.Entrepreneur) {
92
+ account.private_account.entrepreneur_data = newData as IEntrepreneurData
93
+ } else if (account.private_account?.type === AccountTypes.Organization) {
94
+ account.private_account.organization_data = newData as IOrganizationData
95
+ }
96
+
97
+ };
98
+
99
+
100
+ // `Map` для отслеживания состояния раскрытых строк и вкладок
101
+ const expanded = reactive(new Map<string, boolean>())
102
+ const currentTab = reactive<Record<string, string>>({})
103
+
104
+ // Определяем, какой компонент использовать
105
+ const useComponent = (account: IAccount) => {
106
+ if (account.private_account)
107
+ switch (account.private_account.type) {
108
+ case AccountTypes.Individual:
109
+ return EditableIndividualCard
110
+ case AccountTypes.Entrepreneur:
111
+ return EditableEntrepreneurCard
112
+ case AccountTypes.Organization:
113
+ return EditableOrganizationCard
114
+ }
115
+ }
116
+
117
+ const usePrivateData = (account: IAccount) => {
118
+ if (account.private_account)
119
+ switch (account.private_account.type) {
120
+ case AccountTypes.Individual:
121
+ return account.private_account?.individual_data
122
+ case AccountTypes.Entrepreneur:
123
+ return account.private_account?.entrepreneur_data
124
+ case AccountTypes.Organization:
125
+ return account.private_account?.organization_data
126
+ }
127
+ }
128
+
129
+ // Загружаем данные
130
+ const loadParticipants = async () => {
131
+ try {
132
+ onLoading.value = true
133
+
134
+ await accountStore.getAccounts({options: {
135
+ page: 1,
136
+ limit: 1000,
137
+ sortOrder: 'DESC'
138
+ }})
139
+
140
+ onLoading.value = false
141
+ } catch (e: any) {
142
+ onLoading.value = false
143
+ Notify.create({
144
+ message: e.message,
145
+ type: 'negative',
146
+ })
147
+ }
76
148
  }
77
- }
78
-
79
- loadParticipants()
80
-
81
- const columns = [
82
- { name: 'username', align: 'left', label: 'Аккаунт', field: 'username', sortable: true },
83
- { name: 'last_name', align: 'left', label: 'Фамилия', field: 'last_name', sortable: true },
84
- { name: 'first_name', align: 'left', label: 'Имя', field: 'first_name', sortable: true },
85
- { name: 'middle_name', align: 'left', label: 'Отчество', field: 'middle_name', sortable: true },
86
-
87
- { name: 'phone', align: 'left', label: 'Телефон', field: 'phone', sortable: false },
88
- { name: 'email', align: 'left', label: 'Е-почта', field: 'email', sortable: false },
89
- { name: 'birthday', align: 'left', label: 'Дата рождения', field: 'birthday', sortable: true },
90
- {
91
- name: 'created_at',
92
- align: 'left',
93
- label: 'Зарегистрирован',
94
- field: 'created_at',
95
- sortable: true,
96
- },
97
- ] as any
98
149
 
99
- const expanded = ref([])
100
- const tableRef = ref(null)
101
- const pagination = ref({ rowsPerPage: 10 })
150
+ loadParticipants()
151
+
152
+ const columns = [
153
+ { name: 'name', align: 'left', label: 'ФИО / Наименование', field: 'name', sortable: true },
154
+ { name: 'type', align: 'left', label: 'Тип', field: 'type' },
155
+ { name: 'username', align: 'left', label: 'Аккаунт', field: 'username', sortable: true },
156
+ {
157
+ name: 'created_at',
158
+ align: 'left',
159
+ label: 'Зарегистрирован',
160
+ field: 'created_at',
161
+ sortable: true,
162
+ },
163
+ ] as any
164
+
165
+ const tableRef = ref(null)
166
+ const pagination = ref({ rowsPerPage: 10 })
167
+
168
+ // Функция для переключения раскрытия строки
169
+ const toggleExpand = (id: string) => {
170
+ expanded.set(id, !expanded.get(id))
171
+ if (!currentTab[id]) {
172
+ currentTab[id] = 'info' // Устанавливаем вкладку по умолчанию
173
+ }
174
+ }
175
+
176
+ const getName = (account: IAccount) => {
177
+ if (account?.private_account?.type === AccountTypes.Individual){
178
+ return `${account.private_account.individual_data?.last_name} ${account.private_account.individual_data?.first_name} ${account.private_account.individual_data?.middle_name}`
179
+ } else if (account?.private_account?.type === AccountTypes.Entrepreneur){
180
+ return `${account.private_account.entrepreneur_data?.last_name} ${account.private_account.entrepreneur_data?.first_name} ${account.private_account.entrepreneur_data?.middle_name}`
181
+ } else if (account?.private_account?.type === AccountTypes.Organization){
182
+ return `${account.private_account.organization_data?.short_name}`
183
+ }
184
+ }
102
185
 
103
- </script>
186
+ </script>