feat: добавлено отображение статуса делеганта и того кто его назначил

This commit is contained in:
Тимур Городецкий
2026-08-17 12:06:09 +05:00
parent a937e33f2e
commit e6ca84827a
8 changed files with 91 additions and 156 deletions
@@ -13,6 +13,7 @@ import {
searchOwnRequests,
} from './myRequests.service';
import { IMyRequest } from './models/IMyRequest';
import { DataTable, IDataTableColumn } from '@tnsu/ui-kit';
import { REQUEST_STATUS, REQUEST_STATUS_CHOICES, IRequestType, StatusBadge } from '../../shared/approval';
import { onRequestsChanged } from '../../shared/requestEvents';
import { useRoutedQuery } from '../../shared/usePersistedQuery';
@@ -201,61 +202,50 @@ const Table: React.FC<{
statusFilter: string;
onOpen: (request: IMyRequest) => void;
}> = ({ rows, view, statusFilter, onOpen }) => {
const columns = columnsFor(view, statusFilter);
const cols = columnsFor(view, statusFilter);
// Колонки для DataTable строим динамически: базовые всегда, автор/статус/
// комментарий — по columnsFor (зависит от раздела и фильтра). Кастомные ячейки
// (статус → StatusBadge, дата → формат) задаются через render.
const columns: IDataTableColumn<IMyRequest>[] = [
{ key: 'id', title: 'ID', width: '70px' },
{ key: 'type', title: 'Тип', width: '200px', render: (r) => r.requestTypeName },
{ key: 'title', title: 'Название', render: (r) => r.title || `#${r.id}` },
{ key: 'date', title: 'Дата', width: '110px', render: (r) => formatDate(r.created) }
];
if (cols.author) {
columns.push({
key: 'author',
title: 'Автор',
width: '280px',
render: (r) => [r.authorName, r.authorEmail].filter(Boolean).join(' · ') || '—'
});
}
if (cols.status) {
columns.push({
key: 'status',
title: 'Статус',
width: '190px',
render: (r) => (r.status ? <StatusBadge status={r.status} size="sm" /> : '—')
});
}
if (cols.commentLabel) {
columns.push({
key: 'comment',
title: cols.commentLabel,
render: (r) => r.decisionComment || <span className={styles.commentEmpty}>Без комментария</span>
});
}
return (
<div className={styles.tableWrap}>
<table className={styles.table}>
<thead>
<tr>
<th className={styles.colId}>ID</th>
<th className={styles.colType}>Тип</th>
<th className={styles.colTitle}>Название</th>
<th className={styles.colDate}>Дата</th>
{columns.author && <th className={styles.colAuthor}>Автор</th>}
{columns.status && <th className={styles.colStatus}>Статус</th>}
{columns.commentLabel && <th className={styles.colComment}>{columns.commentLabel}</th>}
</tr>
</thead>
<tbody>
{rows.map((r) => (
<tr
className={styles.row}
key={`${r.requestTypeId}-${r.id}`}
tabIndex={0}
role="button"
aria-label={`Открыть заявку «${r.title || r.id}»`}
onClick={() => onOpen(r)}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
onOpen(r);
}
}}
>
<td className={styles.colId}>{r.id}</td>
<td className={styles.colType}>{r.requestTypeName}</td>
<td className={styles.colTitle}>{r.title || `#${r.id}`}</td>
<td className={styles.colDate}>{formatDate(r.created)}</td>
{columns.author && (
<td className={styles.colAuthor}>
{[r.authorName, r.authorEmail].filter(Boolean).join(' · ') || '—'}
</td>
)}
{columns.status && (
<td className={styles.colStatus}>
{r.status ? <StatusBadge status={r.status} size="sm" /> : '—'}
</td>
)}
{columns.commentLabel && (
<td className={styles.colComment}>
{r.decisionComment || <span className={styles.commentEmpty}>Без комментария</span>}
</td>
)}
</tr>
))}
</tbody>
</table>
</div>
<div className={styles.tableWrap}>
<DataTable
columns={columns}
rows={rows}
rowKey={(r) => `${r.requestTypeId}-${r.id}`}
onRowClick={onOpen}
/>
</div>
);
};