import { Form, Input, Modal, Select, message } from 'antd'; import { useState } from 'react'; import { ApiError } from '../../api/client'; import { TableTag } from '../../components/TableTag/TableTag'; import { useBeforeUnload } from '../../hooks/useBeforeUnload'; import { updateStatus } from '../../services/api/consolidations'; import type { VersionStatusUpdate } from '../../types/api'; import type { ConsStatus } from '../../types/consolidations/common_types'; import type { VersionCard } from '../../types/consolidations/version_members'; import { CONS_STATUS_LABEL, MAX_REASON_LENGTH, canSubmitStatusChange, manualTransitions } from '../../utils/consolidations'; import { statusColorMapping } from '../ConsoleTable/consts'; import CustomModalCloseIcon from '../../components/CustomModalCloseIcon'; type StatusModalProps = { open: boolean; /** Карточка версии со страницы: из неё текущий статус и допустимые переходы. */ card: VersionCard; onClose: () => void; /** 200: карточка из ответа `POST …/status` — экран берёт её вместо повторного GET. */ onSuccess: (card: VersionCard) => void; }; type FormValues = { to_status?: ConsStatus; comment?: string }; /** «Изменить статус» [33-01]: варианты — ручные переходы (`MANUAL_TRANSITIONS`), по умолчанию ничего не выбрано. */ export default function ChangeStatusModal({ open, card, onClose, onSuccess }: StatusModalProps) { const [form] = Form.useForm(); const [submitting, setSubmitting] = useState(false); // до монтирования формы useWatch отдаёт undefined — правила это учитывают const nextStatus = Form.useWatch('to_status', form); const comment = Form.useWatch('comment', form); const currentLabel = CONS_STATUS_LABEL[card.status]; const options = manualTransitions(card.status).map((s) => ({ value: s, label: CONS_STATUS_LABEL[s] })); const canSubmit = canSubmitStatusChange(nextStatus, comment); useBeforeUnload(open && (!!nextStatus || !!comment?.trim())); const handleOk = async () => { if (!nextStatus || !canSubmit || submitting) return; const body: VersionStatusUpdate = { to_status: nextStatus, comment: (comment ?? '').trim() }; setSubmitting(true); try { const newCard = await updateStatus(card.id, body); onSuccess(newCard); message.success(`Статус изменён: ${CONS_STATUS_LABEL[newCard.status]}`); onClose(); } catch (e) { // 409 VERSION_NOT_EDITABLE / LOCK_REQUIRED / LOCKED_BY_OTHER / TRANSITION_NOT_ALLOWED, 422 COMMENT_REQUIRED — // текст сервера; модалка открыта, статус на экране прежний message.error(e instanceof ApiError ? e.message : 'Не удалось изменить статус'); } finally { setSubmitting(false); } }; return ( !submitting && onClose()} destroyOnHidden centered closeIcon={}>
Текущий этап