arm-core/web/src/widgets/StatusChangeModal/ChangeStatusModal.tsx

109 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Form, Input, message, Modal, Select } from 'antd';
import { useEffect, useState } from 'react';
import { ConsStatus } from '../../types/consolidations/common_types';
import { VersionStatusUpdate } from '../../types/api';
import { getVersionCard, updateStatus } from '../../services/api/consolidations';
import { statusColorMapping, statusMapping } from '../ConsoleTable/consts';
import { TableTag } from '../../components/TableTag/TableTag';
import { TAG_PRESETS } from '../../components/TableTag/presets';
import { ApiError } from '../../api/client';
import { VersionCard } from '../../types/consolidations/version_members';
type StatusModalProps = {
open: boolean;
versionId: string;
setClose: () => void;
onSuccess: (card: VersionCard) => void;
};
const known409Codes = ['VERSION_NOT_EDITABLE', 'LOCK_REQUIRED', 'LOCKED_BY_OTHER', 'TRANSITION_NOT_ALLOWED'];
const errorCodeMap = {
VERSION_NOT_EDITABLE: 'Версию нельзя отредактировать',
LOCK_REQUIRED: 'Сначала возьмите версию в работу',
LOCKED_BY_OTHER: 'Версия находится в работе у другого пользователя',
TRANSITION_NOT_ALLOWED: 'Данный переход недоступен',
};
async function mockStatusMappingFetch() {
const mapping: Record<ConsStatus, ConsStatus[]> = {
INITIATED: ['CANCELLED'],
DOCUMENTS_PROCESSING: ['CANCELLED', 'INITIATED'],
DATA_CORRECTION: ['CANCELLED', 'INITIATED'],
};
return mapping;
}
export default function ChangeStatusModal({ open, versionId, setClose, onSuccess }: StatusModalProps) {
const [currentStatus, setCurrentStatus] = useState<ConsStatus | null>(null);
const [nextStatusOptions, setNextStatusOptions] = useState<ConsStatus[]>([]);
const [loading, setLoading] = useState(false);
const [form] = Form.useForm<VersionStatusUpdate>();
const nextStatus = Form.useWatch('to_status', form);
const comment = Form.useWatch('comment', form);
useEffect(() => {
async function getAllData() {
if (!versionId) return;
setLoading(true);
const versionCard = await getVersionCard(versionId);
const status = versionCard.status;
const allNextOptions = await mockStatusMappingFetch();
setCurrentStatus(status);
setNextStatusOptions(allNextOptions[status]);
setLoading(false);
}
getAllData();
}, [versionId]);
const russianStatus = currentStatus ? statusMapping[currentStatus] : '';
const badgePreset = russianStatus ? statusColorMapping[russianStatus] : TAG_PRESETS.default;
const isSubmitDisabled = !nextStatus || !comment.trim();
const handleOk = async () => {
const values = await form.validateFields();
try {
const newCard = await updateStatus(versionId, { ...values, comment: values.comment.trim() });
onSuccess(newCard);
setClose();
} catch (e) {
if (e instanceof ApiError && e.status === 409 && e.code) {
if (known409Codes.includes(e.code)) {
message.error(errorCodeMap[e.code]);
}
} else {
message.error('Непредвиденная ошибка');
}
}
};
return (
<Modal
open={open}
title='Изменить статус'
okText='Изменить статус'
cancelText='Отмена'
okButtonProps={{ disabled: isSubmitDisabled || loading }}
loading={loading}
onOk={handleOk}
onCancel={setClose}
destroyOnHidden>
<div style={{ display: 'flex' }}>
Текущий этап: <TableTag text={russianStatus} {...badgePreset} />
</div>
{nextStatusOptions && (
<Form form={form} layout='vertical' requiredMark={false} initialValues={{ comment: '', to_status: nextStatusOptions[0] }}>
<Form.Item name='to_status' label='Новый этап'>
<Select
options={nextStatusOptions.map((i) => ({ label: i, value: i }))}
labelRender={(v) => (v.value ? statusMapping[v.value as ConsStatus] : v.value)}
optionRender={(v) => (v.value ? statusMapping[v.value as ConsStatus] : v.value)}></Select>
</Form.Item>
<Form.Item name='comment' rules={[{ required: true, message: 'Комментарий необходим' }]} label='Комментарий'>
<Input.TextArea maxLength={1000} placeholder='Укажите комментарий к изменению статуса'></Input.TextArea>
</Form.Item>
</Form>
)}
</Modal>
);
}