fix: changed SP list order field to StepOrder
This commit is contained in:
@@ -8,25 +8,40 @@ import { UserPicker } from './UserPicker';
|
||||
export interface IApprovalMatrixProps {
|
||||
editor: IUseMatrixEditor;
|
||||
search: (query: string) => Promise<ISiteUser[]>;
|
||||
/** Заголовок блока. По умолчанию — «Маршрут согласования». */
|
||||
title?: string;
|
||||
/** Подпись роли в шапке таблицы. По умолчанию — «Согласующий». */
|
||||
roleLabel?: string;
|
||||
/** Текст, когда участников нет. По умолчанию — «Согласующие не заданы.». */
|
||||
emptyText?: string;
|
||||
/** Плейсхолдер пикера добавления (только если editor.editable). */
|
||||
pickerPlaceholder?: string;
|
||||
}
|
||||
|
||||
/** Таблица маршрута согласования + (если editable) правка порядка/состава. */
|
||||
export const ApprovalMatrix: React.FC<IApprovalMatrixProps> = ({ editor, search }) => {
|
||||
/** Таблица маршрута (согласование или исполнение) + (если editable) правка состава. */
|
||||
export const ApprovalMatrix: React.FC<IApprovalMatrixProps> = ({
|
||||
editor,
|
||||
search,
|
||||
title = 'Маршрут согласования',
|
||||
roleLabel = 'Согласующий',
|
||||
emptyText = 'Согласующие не заданы.',
|
||||
pickerPlaceholder = 'Добавить согласующего: начните вводить ФИО…',
|
||||
}) => {
|
||||
const { rows, loading, error, editable } = editor;
|
||||
|
||||
return (
|
||||
<div className={styles.matrixWrap}>
|
||||
<div className={styles.matrixTitle}>Маршрут согласования</div>
|
||||
<div className={styles.matrixTitle}>{title}</div>
|
||||
{loading && <div className={styles.matrixNote}>Загрузка маршрута…</div>}
|
||||
{!loading && error && <div className={styles.matrixNote}>Маршрут недоступен: {error}</div>}
|
||||
{!loading && !error && rows.length === 0 && (
|
||||
<div className={styles.matrixNote}>Согласующие не заданы.</div>
|
||||
<div className={styles.matrixNote}>{emptyText}</div>
|
||||
)}
|
||||
{!loading && !error && rows.length > 0 && (
|
||||
<table className={styles.matrix}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Согласующий</th>
|
||||
<th>{roleLabel}</th>
|
||||
<th>Должность</th>
|
||||
<th>Статус</th>
|
||||
<th>Дата</th>
|
||||
@@ -77,11 +92,7 @@ export const ApprovalMatrix: React.FC<IApprovalMatrixProps> = ({ editor, search
|
||||
)}
|
||||
{editable && !loading && (
|
||||
<div className={styles.matrixPicker}>
|
||||
<UserPicker
|
||||
search={search}
|
||||
onPick={editor.addApprover}
|
||||
placeholder="Добавить согласующего: начните вводить ФИО…"
|
||||
/>
|
||||
<UserPicker search={search} onPick={editor.addApprover} placeholder={pickerPlaceholder} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useState, useEffect } from 'react';
|
||||
import styles from './DecisionPanel.module.scss';
|
||||
import { Button, Alert, FormField, TextArea, Icon } from '../../ui';
|
||||
import { ApproverService, ApproverDecision } from '../approverDecision.service';
|
||||
import { APPROVAL_PHASE } from '../models/statuses';
|
||||
|
||||
interface IDecisionPanelProps {
|
||||
service: ApproverService;
|
||||
@@ -17,6 +18,7 @@ interface IDecisionPanelProps {
|
||||
export const DecisionPanel: React.FC<IDecisionPanelProps> = ({ service, requestId, onDecided }) => {
|
||||
const [checking, setChecking] = useState<boolean>(true);
|
||||
const [rowId, setRowId] = useState<number | undefined>(undefined);
|
||||
const [phase, setPhase] = useState<string>(APPROVAL_PHASE.approval);
|
||||
const [comment, setComment] = useState<string>('');
|
||||
const [submitting, setSubmitting] = useState<boolean>(false);
|
||||
const [resultStatus, setResultStatus] = useState<string | undefined>(undefined);
|
||||
@@ -30,6 +32,9 @@ export const DecisionPanel: React.FC<IDecisionPanelProps> = ({ service, requestI
|
||||
.then((row) => {
|
||||
if (alive) {
|
||||
setRowId(row?.id);
|
||||
if (row) {
|
||||
setPhase(row.phase);
|
||||
}
|
||||
setChecking(false);
|
||||
}
|
||||
})
|
||||
@@ -67,14 +72,19 @@ export const DecisionPanel: React.FC<IDecisionPanelProps> = ({ service, requestI
|
||||
}
|
||||
}
|
||||
|
||||
const isExecution = phase === APPROVAL_PHASE.execution;
|
||||
|
||||
if (checking) {
|
||||
return <div className={styles.state}>Проверяем вашу очередь на согласование…</div>;
|
||||
return <div className={styles.state}>Проверяем вашу очередь…</div>;
|
||||
}
|
||||
|
||||
if (resultStatus) {
|
||||
return (
|
||||
<div className={styles.panel}>
|
||||
<Alert variant="ok">Решение сохранено. Статус заявки: «{resultStatus}».</Alert>
|
||||
<Alert variant="ok">
|
||||
{isExecution ? 'Отмечено как выполнено' : 'Решение сохранено'}. Статус заявки: «
|
||||
{resultStatus}».
|
||||
</Alert>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -82,9 +92,33 @@ export const DecisionPanel: React.FC<IDecisionPanelProps> = ({ service, requestI
|
||||
if (rowId === undefined) {
|
||||
return (
|
||||
<div className={styles.panel}>
|
||||
<Alert variant="warn">
|
||||
Сейчас не ваша очередь на согласование, либо заявка уже обработана.
|
||||
</Alert>
|
||||
<Alert variant="warn">Сейчас не ваша очередь, либо заявка уже обработана.</Alert>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Фаза исполнения: одно действие «Выполнено» (без обязательного комментария),
|
||||
// строка помечается как «Согласовано» → computeRequestStatus переведёт заявку в
|
||||
// «Выполнение»/«Закрыта».
|
||||
if (isExecution) {
|
||||
return (
|
||||
<div className={styles.panel}>
|
||||
<div className={styles.title}>Исполнение</div>
|
||||
{error && <Alert variant="err">{error}</Alert>}
|
||||
<FormField label="Комментарий" htmlFor="decisionComment">
|
||||
<TextArea
|
||||
id="decisionComment"
|
||||
value={comment}
|
||||
onChange={setComment}
|
||||
placeholder="Комментарий (необязательно)"
|
||||
/>
|
||||
</FormField>
|
||||
<div className={styles.actions}>
|
||||
<Button variant="accent" disabled={submitting} onClick={() => decide('approve')}>
|
||||
<Icon name="check" size="sm" />
|
||||
Выполнено
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user