fix(install): блокировать «Продолжить» до минимума совета, удаление без ограничений.
На prod требуется 3 человека (на dev — 1): кнопка и подсказка, состав редактируется свободно до перехода на следующий шаг. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1 +1,5 @@
|
||||
export { getMinSovietMembersCount } from './minSovietMembers';
|
||||
export {
|
||||
getMinSovietMembersCount,
|
||||
getSovietMembersProgressHint,
|
||||
getSovietContinueBlockedTooltip,
|
||||
} from './minSovietMembers';
|
||||
|
||||
@@ -4,3 +4,26 @@ import { env } from 'src/shared/config';
|
||||
export function getMinSovietMembersCount(): number {
|
||||
return env.NODE_ENV === 'production' ? 3 : 1;
|
||||
}
|
||||
|
||||
/** Краткая подсказка под формой: сколько указано и чего не хватает. */
|
||||
export function getSovietMembersProgressHint(currentCount: number, min = getMinSovietMembersCount()): string | null {
|
||||
if (min <= 1 || currentCount >= min) return null;
|
||||
const missing = min - currentCount;
|
||||
return `Указано ${currentCount} из ${min}. Добавьте ещё ${missing} ${pluralCouncilSlot(missing)}.`;
|
||||
}
|
||||
|
||||
/** Текст для tooltip заблокированной кнопки «Продолжить». */
|
||||
export function getSovietContinueBlockedTooltip(currentCount: number, min = getMinSovietMembersCount()): string {
|
||||
if (currentCount >= min) return '';
|
||||
if (min === 1) return 'Заполните данные председателя';
|
||||
const missing = min - currentCount;
|
||||
return `Для продолжения нужно ${min} человека в составе совета (ещё ${missing} ${pluralCouncilSlot(missing)})`;
|
||||
}
|
||||
|
||||
function pluralCouncilSlot(count: number): string {
|
||||
const mod10 = count % 10;
|
||||
const mod100 = count % 100;
|
||||
if (mod10 === 1 && mod100 !== 11) return 'человек';
|
||||
if (mod10 >= 2 && mod10 <= 4 && (mod100 < 10 || mod100 >= 20)) return 'человека';
|
||||
return 'человек';
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<template lang="pug">
|
||||
.set-soviet(v-if='installStore')
|
||||
p.set-soviet__requirement(v-if='minSovietMembers > 1')
|
||||
| В составе совета — минимум {{ minSovietMembers }} человека: председатель и члены совета.
|
||||
|
||||
.soviet-member(v-for='(member, index) in installStore.soviet', :key='member.id')
|
||||
.soviet-member__head
|
||||
span.soviet-member__role
|
||||
@@ -29,6 +32,8 @@
|
||||
:rules='[val => notEmpty(val), val => validEmail(val)]'
|
||||
)
|
||||
|
||||
p.set-soviet__progress(v-if='progressHint') {{ progressHint }}
|
||||
|
||||
.set-soviet__actions
|
||||
BaseButton(variant='ghost', @click='back')
|
||||
q-icon(name='arrow_back', size='16px')
|
||||
@@ -37,18 +42,29 @@
|
||||
BaseButton(variant='secondary', @click='add')
|
||||
q-icon(name='add', size='16px')
|
||||
span.q-ml-sm Добавить члена совета
|
||||
BaseButton(variant='primary', :loading='loading', @click='next')
|
||||
span.q-mr-sm Продолжить
|
||||
q-icon(name='arrow_forward', size='16px')
|
||||
span.set-soviet__continue-wrap
|
||||
q-tooltip(v-if='!canContinue') {{ continueBlockedTooltip }}
|
||||
BaseButton(
|
||||
variant='primary',
|
||||
:loading='loading',
|
||||
:disabled='!canContinue',
|
||||
@click='next'
|
||||
)
|
||||
span.q-mr-sm Продолжить
|
||||
q-icon(name='arrow_forward', size='16px')
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { ref, computed } from 'vue';
|
||||
import { useInstallCooperativeStore } from 'src/entities/Installer/model';
|
||||
import { IndividualDataForm } from 'src/shared/ui/UserDataForm/IndividualDataForm';
|
||||
import type { IIndividualData } from 'src/shared/lib/types/user/IUserData';
|
||||
import { FailAlert } from 'src/shared/api';
|
||||
import { getMinSovietMembersCount } from '../../lib';
|
||||
import {
|
||||
getMinSovietMembersCount,
|
||||
getSovietMembersProgressHint,
|
||||
getSovietContinueBlockedTooltip,
|
||||
} from '../../lib';
|
||||
import { notEmpty } from 'src/shared/lib/utils';
|
||||
import { validEmail } from 'src/shared/lib/utils/validEmailRule';
|
||||
import { BaseButton } from 'src/shared/ui/base/BaseButton';
|
||||
@@ -58,6 +74,13 @@ const minSovietMembers = getMinSovietMembersCount();
|
||||
|
||||
installStore.is_finish = false;
|
||||
|
||||
const sovietCount = computed(() => installStore.soviet.length);
|
||||
const canContinue = computed(() => sovietCount.value >= minSovietMembers);
|
||||
const progressHint = computed(() => getSovietMembersProgressHint(sovietCount.value, minSovietMembers));
|
||||
const continueBlockedTooltip = computed(() =>
|
||||
getSovietContinueBlockedTooltip(sovietCount.value, minSovietMembers),
|
||||
);
|
||||
|
||||
const add = () => {
|
||||
let role: 'chairman' | 'member' = 'chairman';
|
||||
|
||||
@@ -76,24 +99,15 @@ const back = () => {
|
||||
installStore.current_step = 'init';
|
||||
};
|
||||
|
||||
const MIN_SOVIET_MEMBERS = minSovietMembers;
|
||||
|
||||
const next = async () => {
|
||||
try {
|
||||
if (installStore.soviet.length < MIN_SOVIET_MEMBERS) {
|
||||
FailAlert(
|
||||
MIN_SOVIET_MEMBERS === 1
|
||||
? 'Необходимо добавить хотя бы одного члена совета'
|
||||
: `Необходимо добавить не менее ${MIN_SOVIET_MEMBERS} членов совета (председатель и члены совета)`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!canContinue.value) return;
|
||||
|
||||
try {
|
||||
loading.value = true;
|
||||
installStore.current_step = 'vars';
|
||||
loading.value = false;
|
||||
} catch (e: any) {
|
||||
FailAlert(e);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
@@ -112,6 +126,18 @@ if (installStore.soviet.length == 0) {
|
||||
gap: var(--p-4, 16px);
|
||||
}
|
||||
|
||||
.set-soviet__requirement,
|
||||
.set-soviet__progress {
|
||||
margin: 0;
|
||||
font-size: var(--p-fs-body-sm, 13px);
|
||||
line-height: var(--p-lh-body, 1.55);
|
||||
color: var(--p-ink-2);
|
||||
}
|
||||
|
||||
.set-soviet__progress {
|
||||
color: var(--p-warn, var(--p-ink-2));
|
||||
}
|
||||
|
||||
.soviet-member {
|
||||
padding: var(--p-4, 16px);
|
||||
background: var(--p-surface);
|
||||
@@ -143,4 +169,7 @@ if (installStore.soviet.length == 0) {
|
||||
gap: var(--p-2, 8px);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.set-soviet__continue-wrap {
|
||||
display: inline-flex;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
|
||||
//- ---------- Шаг 3: члены совета ----------
|
||||
.install-step(v-else-if='step.key === "soviet"')
|
||||
p.install-step__intro {{ sovietStepIntro }}
|
||||
p.install-step__intro
|
||||
| Укажите председателя и членов совета. Каждому будет создан аккаунт пайщика
|
||||
| и отправлено приглашение на электронную почту.
|
||||
SetSovietForm
|
||||
|
||||
//- ---------- Шаг 4: переменные документов ----------
|
||||
@@ -58,17 +60,10 @@ import { useSystemStore } from 'src/entities/System/model';
|
||||
import { VerticalStepper } from 'src/shared/ui/domain/VerticalStepper';
|
||||
import type { StepperStep } from 'src/shared/ui/domain/VerticalStepper';
|
||||
import { BaseButton } from 'src/shared/ui/base/BaseButton';
|
||||
import { getMinSovietMembersCount } from 'src/features/Installer/lib';
|
||||
|
||||
const router = useRouter();
|
||||
const systemStore = useSystemStore();
|
||||
const installStore = useInstallCooperativeStore();
|
||||
const minSovietMembers = getMinSovietMembersCount();
|
||||
|
||||
const sovietStepIntro =
|
||||
minSovietMembers === 1
|
||||
? 'Введите данные председателя. Будет создан аккаунт пайщика и отправлено приглашение на электронную почту.'
|
||||
: 'Введите данные председателя и не менее двух членов совета (всего минимум 3 человека). Каждому будет создан аккаунт пайщика и отправлено приглашение на электронную почту.';
|
||||
|
||||
const steps: StepperStep[] = [
|
||||
{ key: 'key', label: 'Ключ установки', description: 'Ключ, выданный при регистрации пайщиком' },
|
||||
|
||||
Reference in New Issue
Block a user