109 lines
4.2 KiB
TypeScript
109 lines
4.2 KiB
TypeScript
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>
|
||
);
|
||
}
|