@coopenomics/desktop 2025.5.14 → 2025.6.14
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/.env-example +4 -0
- package/extensions/participant/install.ts +37 -25
- package/extensions/soviet/install.ts +23 -20
- package/package.json +7 -5
- package/src/app/App.vue +1 -0
- package/src/app/providers/routes/index.ts +12 -0
- package/src/app/styles/app.scss +1 -1
- package/src/app/styles/style.css +11 -0
- package/src/css/quasar.variables.scss +1 -1
- package/src/entities/Desktop/model/store.ts +68 -0
- package/src/entities/Desktop/model/types.ts +7 -0
- package/src/entities/Document/model/types.ts +1 -1
- package/src/entities/Meet/api/index.ts +2 -28
- package/src/entities/Meet/model/store.ts +7 -22
- package/src/entities/Wallet/api/index.ts +3 -3
- package/src/env.d.ts +1 -0
- package/src/features/Meet/CloseMeetWithDecision/model/index.ts +119 -17
- package/src/features/Meet/CreateMeet/model/index.ts +51 -9
- package/src/features/Meet/CreateMeet/ui/CreateMeet.vue +37 -6
- package/src/features/Meet/CreateMeet/ui/CreateMeetForm.vue +87 -65
- package/src/features/Meet/GenerateSovietDecision/model/index.ts +14 -4
- package/src/features/Meet/RestartMeet/model/index.ts +121 -3
- package/src/features/Meet/RestartMeet/ui/RestartMeet.vue +4 -6
- package/src/features/Meet/RestartMeet/ui/RestartMeetForm.vue +64 -28
- package/src/features/Meet/SignNotification/index.ts +2 -0
- package/src/features/Meet/SignNotification/model/index.ts +137 -0
- package/src/features/Meet/SignNotification/ui/SignNotificationButton.vue +61 -0
- package/src/features/Meet/SignNotification/ui/index.ts +1 -0
- package/src/features/Meet/VoteOnMeet/model/composable.ts +180 -0
- package/src/features/Meet/VoteOnMeet/model/index.ts +2 -17
- package/src/features/Meet/VoteOnMeet/model/types.ts +4 -0
- package/src/features/Meet/index.ts +6 -0
- package/src/features/User/LoginRedirect/ui/LoginRedirectPage.vue +15 -0
- package/src/features/User/LoginRedirect/ui/index.ts +1 -0
- package/src/features/User/LoginUser/ui/LoginForm/LoginForm.vue +38 -1
- package/src/features/User/LoginWithRedirect/ui/LoginRedirectForm/LoginRedirectForm.vue +0 -0
- package/src/pages/Cooperative/ListOfMeets/ui/ListOfMeetsPage.vue +22 -46
- package/src/pages/Cooperative/MeetDetails/ui/MeetDetailsPage.vue +84 -28
- package/src/pages/PermissionDenied/PermissionDenied.vue +1 -1
- package/src/processes/init-app/index.ts +12 -5
- package/src/processes/navigation-guard-setup/index.ts +37 -5
- package/src/processes/process-decisions/index.ts +7 -6
- package/src/shared/config/Environment.ts +10 -2
- package/src/shared/lib/composables/index.ts +1 -0
- package/src/shared/lib/composables/useMeetStatus.ts +96 -0
- package/src/shared/lib/consts/index.ts +1 -0
- package/src/shared/lib/consts/meet-statuses.ts +114 -0
- package/src/shared/lib/document/model/entity.ts +4 -2
- package/src/shared/lib/types/certificate/index.ts +6 -0
- package/src/shared/lib/types/document/index.ts +1 -1
- package/src/shared/lib/types/workspace.ts +24 -0
- package/src/shared/lib/utils/dates/index.ts +5 -0
- package/src/shared/lib/utils/dates/moment.ts +43 -2
- package/src/shared/lib/utils/dates/timezone.ts +75 -0
- package/src/shared/lib/utils/getNameFromCertificate.ts +108 -0
- package/src/shared/lib/utils/index.ts +1 -0
- package/src/shared/lib/utils/parseLinks.ts +10 -0
- package/src/shared/ui/AgendaNumberAvatar/AgendaNumberAvatar.vue +12 -0
- package/src/shared/ui/AgendaNumberAvatar/index.ts +1 -0
- package/src/shared/ui/BaseDocument/BaseDocument.vue +37 -8
- package/src/shared/ui/ExpandableDocument/ExpandableDocument.vue +49 -0
- package/src/shared/ui/ExpandableDocument/index.ts +1 -0
- package/src/shared/ui/MeetInfoCard/index.ts +1 -0
- package/src/shared/ui/MeetInfoCard/ui/MeetInfoCard.vue +62 -0
- package/src/shared/ui/MeetStatusBanner/index.ts +1 -0
- package/src/shared/ui/MeetStatusBanner/ui/MeetStatusBanner.vue +94 -0
- package/src/shared/ui/index.ts +1 -0
- package/src/widgets/Cooperative/Documents/ListOfDocuments/ui/DocumentsTable.vue +3 -3
- package/src/widgets/Cooperative/Orders/ListOfOrders/ui/ListOfOrdersWidget.vue +2 -2
- package/src/widgets/Cooperative/Payments/ListOfPayments/ui/ListOfPaymentsWidget.vue +2 -2
- package/src/widgets/Desktop/WorkspaceMenu/WorkspaceMenu.vue +74 -82
- package/src/widgets/Header/CommonHeader/CooperativeSettingsHeader.vue +1 -1
- package/src/widgets/Header/CommonHeader/ExtstoreHeader.vue +1 -1
- package/src/widgets/Header/CommonHeader/MainHeader.vue +6 -0
- package/src/widgets/Header/CommonHeader/UserSettingsHeader.vue +1 -1
- package/src/widgets/Meets/MeetCardsList/index.ts +1 -0
- package/src/widgets/Meets/MeetCardsList/ui/MeetCardsList.vue +55 -0
- package/src/widgets/Meets/MeetDetailsActions/MeetDetailsActions.vue +33 -15
- package/src/widgets/Meets/MeetDetailsAgenda/MeetDetailsAgenda.vue +34 -15
- package/src/widgets/Meets/MeetDetailsInfo/MeetDetailsInfo.vue +27 -0
- package/src/widgets/Meets/MeetDetailsInfo/index.ts +1 -0
- package/src/widgets/Meets/MeetDetailsResults/MeetDetailsResults.vue +129 -0
- package/src/widgets/Meets/MeetDetailsResults/index.ts +1 -0
- package/src/widgets/Meets/MeetDetailsVoting/MeetDetailsVoting.vue +221 -62
- package/src/widgets/Meets/MeetQuorumIndicator/MeetQuorumIndicator.vue +0 -0
- package/src/widgets/Meets/MeetQuorumIndicator/index.ts +1 -0
- package/src/widgets/Meets/MeetQuorumIndicator/ui/MeetQuorumIndicator.vue +35 -0
- package/src/widgets/Meets/MeetsTable/ui/MeetsTable.vue +56 -65
- package/src/widgets/NotificationCenter/NotificationCenter.vue +90 -0
- package/src/widgets/NotificationCenter/index.ts +1 -0
- package/src/widgets/Participants/ui/ParticipantsTable.vue +1 -1
- package/src/widgets/Questions/ui/QuestionsTable/QuestionsTable.vue +22 -10
- package/src/widgets/Questions/ui/VotingButtons/VotingButtons.vue +59 -14
- package/src/widgets/Registrator/AlreadyRegistered/AlreadyRegistered.vue +1 -1
- package/src/widgets/User/PaymentMethods/ui/PaymentMethods.vue +0 -1
- package/src-ssr/middlewares/injectEnv.ts +5 -1
- package/src/features/Meet/GenerateAgenda/index.ts +0 -1
- package/src/features/Meet/GenerateAgenda/model/index.ts +0 -18
- package/src/features/Meet/GenerateBallot/index.ts +0 -1
- package/src/features/Meet/GenerateBallot/model/index.ts +0 -18
- package/src/features/Meet/GenerateNotification/index.ts +0 -1
- package/src/features/Meet/GenerateNotification/model/index.ts +0 -18
- package/src/features/Meet/MeetDetailsManagement/index.ts +0 -1
- package/src/features/Meet/MeetDetailsManagement/model/index.ts +0 -121
- package/src/pages/Cooperative/ListOfMeets/model/index.ts +0 -1
- package/src/pages/Cooperative/ListOfMeets/model/model.ts +0 -117
- package/src/widgets/Meets/MeetDetailsActions/model.ts +0 -46
- package/src/widgets/Meets/MeetDetailsHeader/MeetDetailsHeader.vue +0 -40
- package/src/widgets/Meets/MeetDetailsHeader/index.ts +0 -1
- package/src/widgets/Meets/MeetDetailsVoting/model.ts +0 -117
- package/src/widgets/Meets/MeetInfoCard/ui/MeetInfoCard.vue +0 -38
- package/src/widgets/Meets/MeetInfoCard/ui/index.ts +0 -1
- /package/src/{widgets/Meets/MeetInfoCard → features/User/LoginRedirect}/index.ts +0 -0
@@ -1,121 +0,0 @@
|
|
1
|
-
import { computed, type Ref } from 'vue'
|
2
|
-
import type { IMeet } from 'src/entities/Meet'
|
3
|
-
import { useMeetStore } from 'src/entities/Meet'
|
4
|
-
import { useSessionStore } from 'src/entities/Session'
|
5
|
-
import { FailAlert, SuccessAlert } from 'src/shared/api'
|
6
|
-
import { signByPresiderOnAnnualGeneralMeetWithDecision } from 'src/features/Meet/CloseMeetWithDecision/model'
|
7
|
-
import { restartMeetWithProposal } from 'src/features/Meet/RestartMeet/model'
|
8
|
-
import moment from 'moment-with-locales-es6'
|
9
|
-
|
10
|
-
moment.locale('ru')
|
11
|
-
|
12
|
-
export const useMeetDetailsManagement = (
|
13
|
-
meet: IMeet,
|
14
|
-
coopname: string,
|
15
|
-
meetHash: string,
|
16
|
-
isProcessing: Ref<boolean>
|
17
|
-
) => {
|
18
|
-
const meetStore = useMeetStore()
|
19
|
-
const sessionStore = useSessionStore()
|
20
|
-
|
21
|
-
const canManageMeet = computed(() => true) // Здесь можно добавить проверку ролей
|
22
|
-
|
23
|
-
const canCloseBySecretary = computed(() => {
|
24
|
-
if (!meet?.processing?.meet) return false
|
25
|
-
|
26
|
-
const now = moment()
|
27
|
-
const closeAt = moment(meet.processing.meet.close_at)
|
28
|
-
|
29
|
-
const isAfterCloseDate = now.isAfter(closeAt)
|
30
|
-
const isQuorumPassed = meet.processing.meet.quorum_passed === true
|
31
|
-
const isAuthorized = meet.processing.meet.status === 'authorized'
|
32
|
-
|
33
|
-
return isAfterCloseDate && isQuorumPassed && isAuthorized
|
34
|
-
})
|
35
|
-
|
36
|
-
const canCloseByPresider = computed(() => {
|
37
|
-
if (!meet?.processing?.meet) return false
|
38
|
-
return meet.processing.meet.status === 'preclose'
|
39
|
-
})
|
40
|
-
|
41
|
-
const canRestartMeet = computed(() => {
|
42
|
-
if (!meet?.processing?.meet) return false
|
43
|
-
|
44
|
-
const now = moment()
|
45
|
-
const closeAt = moment(meet.processing.meet.close_at)
|
46
|
-
|
47
|
-
const isAfterCloseDate = now.isAfter(closeAt)
|
48
|
-
const isQuorumNotPassed = meet.processing.meet.quorum_passed !== true
|
49
|
-
|
50
|
-
return isAfterCloseDate && isQuorumNotPassed && meet.processing.meet.status === 'authorized'
|
51
|
-
})
|
52
|
-
|
53
|
-
const closeMeetBySecretary = async () => {
|
54
|
-
isProcessing.value = true
|
55
|
-
try {
|
56
|
-
await signByPresiderOnAnnualGeneralMeetWithDecision({
|
57
|
-
coopname,
|
58
|
-
hash: meetHash,
|
59
|
-
username: sessionStore.username,
|
60
|
-
})
|
61
|
-
|
62
|
-
await meetStore.loadMeet({ coopname, hash: meetHash })
|
63
|
-
SuccessAlert('Собрание успешно закрыто')
|
64
|
-
} catch (error: any) {
|
65
|
-
FailAlert(error)
|
66
|
-
} finally {
|
67
|
-
isProcessing.value = false
|
68
|
-
}
|
69
|
-
}
|
70
|
-
|
71
|
-
const closeMeetByPresider = async () => {
|
72
|
-
isProcessing.value = true
|
73
|
-
try {
|
74
|
-
await signByPresiderOnAnnualGeneralMeetWithDecision({
|
75
|
-
coopname,
|
76
|
-
hash: meetHash,
|
77
|
-
username: sessionStore.username,
|
78
|
-
})
|
79
|
-
|
80
|
-
await meetStore.loadMeet({ coopname, hash: meetHash })
|
81
|
-
SuccessAlert('Собрание успешно закрыто')
|
82
|
-
} catch (error: any) {
|
83
|
-
FailAlert(error)
|
84
|
-
} finally {
|
85
|
-
isProcessing.value = false
|
86
|
-
}
|
87
|
-
}
|
88
|
-
|
89
|
-
const handleRestartMeet = async (data: any) => {
|
90
|
-
isProcessing.value = true
|
91
|
-
try {
|
92
|
-
await restartMeetWithProposal({
|
93
|
-
coopname,
|
94
|
-
hash: meetHash,
|
95
|
-
username: sessionStore.username,
|
96
|
-
new_open_at: data.new_open_at,
|
97
|
-
new_close_at: data.new_close_at,
|
98
|
-
agenda_points: data.agenda_points
|
99
|
-
})
|
100
|
-
|
101
|
-
await meetStore.loadMeet({ coopname, hash: meetHash })
|
102
|
-
SuccessAlert('Собрание успешно перезапущено')
|
103
|
-
return true
|
104
|
-
} catch (error: any) {
|
105
|
-
FailAlert(error)
|
106
|
-
return false
|
107
|
-
} finally {
|
108
|
-
isProcessing.value = false
|
109
|
-
}
|
110
|
-
}
|
111
|
-
|
112
|
-
return {
|
113
|
-
canManageMeet,
|
114
|
-
canCloseBySecretary,
|
115
|
-
canCloseByPresider,
|
116
|
-
canRestartMeet,
|
117
|
-
closeMeetBySecretary,
|
118
|
-
closeMeetByPresider,
|
119
|
-
handleRestartMeet
|
120
|
-
}
|
121
|
-
}
|
@@ -1 +0,0 @@
|
|
1
|
-
export * from './model'
|
@@ -1,117 +0,0 @@
|
|
1
|
-
import { computed } from 'vue'
|
2
|
-
import { Notify } from 'quasar'
|
3
|
-
import { useMeetStore } from 'src/entities/Meet/model/store'
|
4
|
-
import { createMeetWithAgenda } from 'src/features/Meet/CreateMeet/model'
|
5
|
-
import { signByPresiderOnAnnualGeneralMeetWithDecision } from 'src/features/Meet/CloseMeetWithDecision/model'
|
6
|
-
import { restartMeetWithProposal } from 'src/features/Meet/RestartMeet/model'
|
7
|
-
import { useSessionStore } from 'src/entities/Session'
|
8
|
-
import type { IMeet } from 'src/entities/Meet'
|
9
|
-
import { FailAlert } from 'src/shared/api'
|
10
|
-
|
11
|
-
export function useMeetManagement(coopname: string) {
|
12
|
-
const meetStore = useMeetStore()
|
13
|
-
const sessionStore = useSessionStore()
|
14
|
-
|
15
|
-
const meets = computed(() => meetStore.meets)
|
16
|
-
const loading = computed(() => meetStore.loading)
|
17
|
-
|
18
|
-
const loadMeets = async () => {
|
19
|
-
try {
|
20
|
-
await meetStore.loadMeets({ coopname })
|
21
|
-
} catch (e: any) {
|
22
|
-
FailAlert(e)
|
23
|
-
}
|
24
|
-
}
|
25
|
-
|
26
|
-
const handleCreateMeet = async (formData: any) => {
|
27
|
-
try {
|
28
|
-
await createMeetWithAgenda({
|
29
|
-
coopname,
|
30
|
-
initiator: formData.initiator,
|
31
|
-
presider: formData.presider,
|
32
|
-
secretary: formData.secretary,
|
33
|
-
open_at: formData.open_at,
|
34
|
-
close_at: formData.close_at,
|
35
|
-
username: sessionStore.username,
|
36
|
-
agenda_points: formData.agenda_points
|
37
|
-
})
|
38
|
-
|
39
|
-
await loadMeets()
|
40
|
-
|
41
|
-
Notify.create({
|
42
|
-
message: 'Собрание успешно создано',
|
43
|
-
type: 'positive',
|
44
|
-
})
|
45
|
-
|
46
|
-
return true
|
47
|
-
} catch (e: any) {
|
48
|
-
FailAlert(e)
|
49
|
-
return false
|
50
|
-
}
|
51
|
-
}
|
52
|
-
|
53
|
-
const handleCloseMeet = async (meet: IMeet) => {
|
54
|
-
try {
|
55
|
-
await signByPresiderOnAnnualGeneralMeetWithDecision({
|
56
|
-
coopname,
|
57
|
-
hash: meet.hash,
|
58
|
-
username: sessionStore.username,
|
59
|
-
})
|
60
|
-
|
61
|
-
await loadMeets()
|
62
|
-
|
63
|
-
Notify.create({
|
64
|
-
message: 'Собрание успешно закрыто',
|
65
|
-
type: 'positive',
|
66
|
-
})
|
67
|
-
|
68
|
-
return true
|
69
|
-
} catch (e: any) {
|
70
|
-
FailAlert(e)
|
71
|
-
return false
|
72
|
-
}
|
73
|
-
}
|
74
|
-
|
75
|
-
const handleRestartMeet = async (data: any) => {
|
76
|
-
try {
|
77
|
-
await restartMeetWithProposal({
|
78
|
-
coopname,
|
79
|
-
hash: data.hash,
|
80
|
-
username: sessionStore.username,
|
81
|
-
new_open_at: data.new_open_at,
|
82
|
-
new_close_at: data.new_close_at,
|
83
|
-
agenda_points: data.agenda_points
|
84
|
-
})
|
85
|
-
|
86
|
-
await loadMeets()
|
87
|
-
|
88
|
-
Notify.create({
|
89
|
-
message: 'Собрание успешно перезапущено',
|
90
|
-
type: 'positive',
|
91
|
-
})
|
92
|
-
|
93
|
-
return true
|
94
|
-
} catch (e: any) {
|
95
|
-
FailAlert(e)
|
96
|
-
return false
|
97
|
-
}
|
98
|
-
}
|
99
|
-
|
100
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
101
|
-
const handleVote = (meet: IMeet) => {
|
102
|
-
Notify.create({
|
103
|
-
message: 'Голосование в разработке',
|
104
|
-
type: 'info',
|
105
|
-
})
|
106
|
-
}
|
107
|
-
|
108
|
-
return {
|
109
|
-
meets,
|
110
|
-
loading,
|
111
|
-
loadMeets,
|
112
|
-
handleCreateMeet,
|
113
|
-
handleCloseMeet,
|
114
|
-
handleRestartMeet,
|
115
|
-
handleVote
|
116
|
-
}
|
117
|
-
}
|
@@ -1,46 +0,0 @@
|
|
1
|
-
import { computed } from 'vue'
|
2
|
-
import type { IMeet } from 'src/entities/Meet'
|
3
|
-
import moment from 'moment-with-locales-es6'
|
4
|
-
|
5
|
-
moment.locale('ru')
|
6
|
-
|
7
|
-
export const useMeetDetailsActions = (meet: IMeet) => {
|
8
|
-
const canManageMeet = computed(() => true) // Здесь можно добавить проверку ролей
|
9
|
-
|
10
|
-
const canCloseBySecretary = computed(() => {
|
11
|
-
if (!meet?.processing?.meet) return false
|
12
|
-
|
13
|
-
const now = moment()
|
14
|
-
const closeAt = moment(meet.processing.meet.close_at)
|
15
|
-
|
16
|
-
const isAfterCloseDate = now.isAfter(closeAt)
|
17
|
-
const isQuorumPassed = meet.processing.meet.quorum_passed === true
|
18
|
-
const isAuthorized = meet.processing.meet.status === 'authorized'
|
19
|
-
|
20
|
-
return isAfterCloseDate && isQuorumPassed && isAuthorized
|
21
|
-
})
|
22
|
-
|
23
|
-
const canCloseByPresider = computed(() => {
|
24
|
-
if (!meet?.processing?.meet) return false
|
25
|
-
return meet.processing.meet.status === 'preclose'
|
26
|
-
})
|
27
|
-
|
28
|
-
const canRestartMeet = computed(() => {
|
29
|
-
if (!meet?.processing?.meet) return false
|
30
|
-
|
31
|
-
const now = moment()
|
32
|
-
const closeAt = moment(meet.processing.meet.close_at)
|
33
|
-
|
34
|
-
const isAfterCloseDate = now.isAfter(closeAt)
|
35
|
-
const isQuorumNotPassed = meet.processing.meet.quorum_passed !== true
|
36
|
-
|
37
|
-
return isAfterCloseDate && isQuorumNotPassed && meet.processing.meet.status === 'authorized'
|
38
|
-
})
|
39
|
-
|
40
|
-
return {
|
41
|
-
canManageMeet,
|
42
|
-
canCloseBySecretary,
|
43
|
-
canCloseByPresider,
|
44
|
-
canRestartMeet
|
45
|
-
}
|
46
|
-
}
|
@@ -1,40 +0,0 @@
|
|
1
|
-
<template lang="pug">
|
2
|
-
q-card(flat class="card-container q-pa-md")
|
3
|
-
div.row.items-center
|
4
|
-
div.col-12
|
5
|
-
div.text-h5.q-mb-xs Общее собрание {{ meet.hash.substring(0, 10) }}
|
6
|
-
q-badge(color="primary" class="meet-status") {{ meetStatus }}
|
7
|
-
div.row.q-mt-md
|
8
|
-
div.col-12
|
9
|
-
MeetInfoCard(:meet="meet")
|
10
|
-
</template>
|
11
|
-
|
12
|
-
<script setup lang="ts">
|
13
|
-
import { MeetInfoCard } from '../MeetInfoCard'
|
14
|
-
import type { IMeet } from 'src/entities/Meet'
|
15
|
-
import { computed } from 'vue';
|
16
|
-
|
17
|
-
const props = defineProps<{
|
18
|
-
meet: IMeet
|
19
|
-
}>()
|
20
|
-
|
21
|
-
const meetStatus = computed(() => {
|
22
|
-
if (!props.meet?.processing?.meet?.status) return 'Неизвестный статус'
|
23
|
-
|
24
|
-
const statusMap = {
|
25
|
-
'created': 'Ожидание решения совета',
|
26
|
-
'authorized': 'Утверждено',
|
27
|
-
'preclose': 'На закрытии',
|
28
|
-
'closed': 'Закрыто'
|
29
|
-
}
|
30
|
-
|
31
|
-
return statusMap[props.meet.processing.meet.status] || 'Неизвестный статус'
|
32
|
-
})
|
33
|
-
</script>
|
34
|
-
|
35
|
-
<style lang="scss" scoped>
|
36
|
-
.meet-status {
|
37
|
-
font-size: 14px;
|
38
|
-
padding: 4px 8px;
|
39
|
-
}
|
40
|
-
</style>
|
@@ -1 +0,0 @@
|
|
1
|
-
export { default as MeetDetailsHeader } from './MeetDetailsHeader.vue'
|
@@ -1,117 +0,0 @@
|
|
1
|
-
import { computed, type Ref } from 'vue'
|
2
|
-
import type { IMeet } from 'src/entities/Meet'
|
3
|
-
import { useMeetStore } from 'src/entities/Meet'
|
4
|
-
import { useSessionStore } from 'src/entities/Session'
|
5
|
-
import { FailAlert, SuccessAlert } from 'src/shared/api'
|
6
|
-
import { voteOnMeet, type IVoteOnMeetInput } from 'src/features/Meet/VoteOnMeet'
|
7
|
-
import { generateBallot } from 'src/features/Meet/GenerateBallot'
|
8
|
-
import { useSignDocument } from 'src/shared/lib/document'
|
9
|
-
import moment from 'moment-with-locales-es6'
|
10
|
-
|
11
|
-
moment.locale('ru')
|
12
|
-
|
13
|
-
export const useMeetDetailsVoting = (
|
14
|
-
meet: IMeet,
|
15
|
-
coopname: string,
|
16
|
-
meetHash: string,
|
17
|
-
votes: Ref<Record<number, 'for' | 'against' | 'abstained'>>,
|
18
|
-
isVoting: Ref<boolean>
|
19
|
-
) => {
|
20
|
-
const meetStore = useMeetStore()
|
21
|
-
const sessionStore = useSessionStore()
|
22
|
-
const { signDocument } = useSignDocument()
|
23
|
-
|
24
|
-
const meetAgendaItems = computed(() => {
|
25
|
-
if (!meet) return []
|
26
|
-
return meet.processing?.questions || []
|
27
|
-
})
|
28
|
-
|
29
|
-
const canVote = computed(() => {
|
30
|
-
if (!meet?.processing?.meet) return false
|
31
|
-
|
32
|
-
const isAuthorized = meet.processing.meet.status === 'authorized'
|
33
|
-
|
34
|
-
const now = moment()
|
35
|
-
const openAt = moment(meet.processing.meet.open_at)
|
36
|
-
const closeAt = moment(meet.processing.meet.close_at)
|
37
|
-
|
38
|
-
const isWithinTimeframe = now.isAfter(openAt) && now.isBefore(closeAt)
|
39
|
-
|
40
|
-
return isAuthorized && isWithinTimeframe
|
41
|
-
})
|
42
|
-
|
43
|
-
const allVotesSelected = computed(() => {
|
44
|
-
if (!meetAgendaItems.value.length) return false
|
45
|
-
return meetAgendaItems.value.every((_, index) => votes.value[index] !== undefined)
|
46
|
-
})
|
47
|
-
|
48
|
-
const isVotingNotStarted = computed(() => {
|
49
|
-
if (!meet?.processing?.meet?.open_at) return false
|
50
|
-
const now = moment()
|
51
|
-
const openAt = moment(meet.processing.meet.open_at)
|
52
|
-
return now.isBefore(openAt)
|
53
|
-
})
|
54
|
-
|
55
|
-
const isVotingEnded = computed(() => {
|
56
|
-
if (!meet?.processing?.meet?.close_at) return false
|
57
|
-
const now = moment()
|
58
|
-
const closeAt = moment(meet.processing.meet.close_at)
|
59
|
-
return now.isAfter(closeAt)
|
60
|
-
})
|
61
|
-
|
62
|
-
const formattedOpenDate = computed(() => {
|
63
|
-
if (!meet?.processing?.meet?.open_at) return ''
|
64
|
-
return moment(meet.processing.meet.open_at).format('DD.MM.YYYY HH:mm')
|
65
|
-
})
|
66
|
-
|
67
|
-
const formattedCloseDate = computed(() => {
|
68
|
-
if (!meet?.processing?.meet?.close_at) return ''
|
69
|
-
return moment(meet.processing.meet.close_at).format('DD.MM.YYYY HH:mm')
|
70
|
-
})
|
71
|
-
|
72
|
-
const submitVote = async () => {
|
73
|
-
if (!meet || !allVotesSelected.value || !canVote.value) return
|
74
|
-
|
75
|
-
isVoting.value = true
|
76
|
-
try {
|
77
|
-
const votesData = meetAgendaItems.value.map((item, index) => ({
|
78
|
-
question_id: item.id,
|
79
|
-
vote: votes.value[index]
|
80
|
-
}))
|
81
|
-
|
82
|
-
const generatedBallot = await generateBallot({
|
83
|
-
coopname,
|
84
|
-
username: sessionStore.username,
|
85
|
-
})
|
86
|
-
|
87
|
-
const signedBallot = await signDocument(generatedBallot, sessionStore.username)
|
88
|
-
|
89
|
-
const vote: IVoteOnMeetInput = {
|
90
|
-
coopname,
|
91
|
-
hash: meetHash,
|
92
|
-
ballot: signedBallot,
|
93
|
-
username: sessionStore.username,
|
94
|
-
votes: votesData
|
95
|
-
}
|
96
|
-
|
97
|
-
await voteOnMeet(vote)
|
98
|
-
SuccessAlert('Ваш голос успешно отправлен')
|
99
|
-
await meetStore.loadMeet({ coopname, hash: meetHash })
|
100
|
-
} catch (error: any) {
|
101
|
-
FailAlert(error)
|
102
|
-
} finally {
|
103
|
-
isVoting.value = false
|
104
|
-
}
|
105
|
-
}
|
106
|
-
|
107
|
-
return {
|
108
|
-
canVote,
|
109
|
-
meetAgendaItems,
|
110
|
-
allVotesSelected,
|
111
|
-
isVotingNotStarted,
|
112
|
-
isVotingEnded,
|
113
|
-
formattedOpenDate,
|
114
|
-
formattedCloseDate,
|
115
|
-
submitVote
|
116
|
-
}
|
117
|
-
}
|
@@ -1,38 +0,0 @@
|
|
1
|
-
<template lang="pug">
|
2
|
-
div.row.q-pa-md
|
3
|
-
div.col-12
|
4
|
-
q-card(flat)
|
5
|
-
q-card-section
|
6
|
-
div.text-h6 Информация о собрании
|
7
|
-
div.q-mt-sm
|
8
|
-
div.row
|
9
|
-
div.col-2.text-weight-bold Статус:
|
10
|
-
div.col {{ meet.processing?.meet?.status }}
|
11
|
-
|
12
|
-
div.row
|
13
|
-
div.col-2.text-weight-bold Инициатор:
|
14
|
-
div.col {{ meet.processing?.meet?.initiator }}
|
15
|
-
div.row
|
16
|
-
div.col-2.text-weight-bold Председатель:
|
17
|
-
div.col {{ meet.processing?.meet?.presider }}
|
18
|
-
div.row
|
19
|
-
div.col-2.text-weight-bold Секретарь:
|
20
|
-
div.col {{ meet.processing?.meet?.secretary }}
|
21
|
-
div.row
|
22
|
-
div.col-2.text-weight-bold Кворум:
|
23
|
-
div.col {{ meet.processing?.meet?.quorum_percent }}%
|
24
|
-
div.row
|
25
|
-
div.col-2.text-weight-bold Текущий кворум:
|
26
|
-
div.col {{ meet.processing?.meet?.current_quorum_percent }}%
|
27
|
-
div.row
|
28
|
-
div.col-2.text-weight-bold Кворум достигнут:
|
29
|
-
div.col {{ meet.processing?.meet?.quorum_passed ? 'Да' : 'Нет' }}
|
30
|
-
</template>
|
31
|
-
|
32
|
-
<script setup lang="ts">
|
33
|
-
import type { IMeet } from 'src/entities/Meet'
|
34
|
-
|
35
|
-
defineProps<{
|
36
|
-
meet: IMeet
|
37
|
-
}>()
|
38
|
-
</script>
|
@@ -1 +0,0 @@
|
|
1
|
-
export { default as MeetInfoCard } from './MeetInfoCard.vue'
|
File without changes
|