diff --git a/src/webparts/requestPortal/features/myRequests/MyRequestsPanel.module.scss b/src/webparts/requestPortal/features/myRequests/MyRequestsPanel.module.scss index b5f2983..2957c0a 100644 --- a/src/webparts/requestPortal/features/myRequests/MyRequestsPanel.module.scss +++ b/src/webparts/requestPortal/features/myRequests/MyRequestsPanel.module.scss @@ -157,77 +157,89 @@ padding: 0 2px; } -.list { - list-style: none; - margin: 0; - padding: 0; - display: flex; - flex-direction: column; - gap: $sp-2; +.table { + width: 100%; + border-collapse: collapse; + table-layout: fixed; + font-size: $fs-caption; + + th { + text-align: left; + font-weight: 600; + color: $gray-500; + font-size: $fs-caption; + text-transform: uppercase; + letter-spacing: .03em; + padding: 6px 8px; + border-bottom: 1px solid $gray-200; + } + + td { + // Высокие строки + перенос по словам: панель узкая, а длинные названия и + // e-mail не должны обрезаться — пусть занимают несколько строк. + height: 66px; + padding: $sp-3 8px; + border-bottom: 1px solid $gray-100; + vertical-align: middle; + white-space: normal; + overflow-wrap: break-word; + word-break: break-word; + line-height: 1.4; + } } -.item { - display: flex; - align-items: center; - justify-content: space-between; - gap: $sp-2; - padding: $sp-2 $sp-3; - border: 1px solid $gray-200; - border-radius: $r-sm; - background: $gray-50; - text-decoration: none; - transition: .16s; +.row { + transition: background .16s; &:hover { - border-color: $gold-400; background: $gold-50; } } -.itemMain { - display: flex; - flex-direction: column; - gap: 2px; - min-width: 0; - overflow: hidden; -} - -.itemType { +.cellType { + width: 72px; color: $gold-600; - font-size: $fs-caption; font-weight: 600; - text-transform: uppercase; - letter-spacing: .03em; } -.itemTitle { +.cellTitle { + // Ширину не задаём — делит оставшееся место с cellAuthor (table-layout: fixed). + min-width: 0; +} + +.titleLink { + display: block; color: $gray-900; - font-size: $fs-sm; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + text-decoration: none; + + &:hover { + color: $gold-600; + text-decoration: underline; + } } -.itemAuthor { +.cellAuthor { color: $gray-500; - font-size: $fs-caption; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; } -.itemDate { +.cellDate { + width: 64px; color: $gray-400; - font-size: $fs-caption; +} + +.cellStatus { + width: 96px; } .status { - flex-shrink: 0; - padding: 2px 8px; - border-radius: $r-full; + // inline-block, а не flex-элемент: бейдж живёт внутри ячейки таблицы и + // переносится по словам (напр. «Возвращена на доработку» в узкой колонке). + display: inline-block; + padding: 3px 8px; + border-radius: $r-md; font-size: $fs-caption; font-weight: 500; - white-space: nowrap; + line-height: 1.3; } .statusDraft { diff --git a/src/webparts/requestPortal/features/myRequests/MyRequestsPanel.tsx b/src/webparts/requestPortal/features/myRequests/MyRequestsPanel.tsx index 44c5363..2212523 100644 --- a/src/webparts/requestPortal/features/myRequests/MyRequestsPanel.tsx +++ b/src/webparts/requestPortal/features/myRequests/MyRequestsPanel.tsx @@ -42,40 +42,61 @@ function statusClass(status: string): string { } } -// «Ждёt вашего решения»: автор здесь — не вы, поэтому важны email + имя, +// «Ждёt вашего решения»: автор здесь — не вы, поэтому важна колонка «Автор», // а статус не нужен (в этой секции все заявки по определению «на согласовании»). -// «Созданы вами»: автор — всегда вы, строку с ним не показываем, зато нужен статус. -const RequestItem: React.FC<{ r: IMyRequest; variant: 'own' | 'approval' }> = ({ r, variant }) => ( -
  • - { - // Обычный левый клик — SPA-переход (без перезагрузки страницы). - // Ctrl/Cmd/Shift/среднюю кнопку — не трогаем, пусть браузер сам - // откроет в новой вкладке по href. - if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) { - return; - } - e.preventDefault(); - navigate({ mode: 'approve', formKey: r.formKey, itemId: r.id }); - }} - > -
    - {r.requestTypeName} - {r.title || `#${r.id}`} - {variant === 'approval' && ( - - {[r.authorName, r.authorEmail].filter(Boolean).join(' · ') || '— автор не определён —'} - - )} - {r.created && {formatDate(r.created)}} -
    - {variant === 'own' && ( +// «Созданы вами»: автор — всегда вы, колонку не показываем, зато нужен статус. +const RequestRow: React.FC<{ r: IMyRequest; variant: 'own' | 'approval' }> = ({ r, variant }) => ( + + {r.requestTypeName} + +
    { + // Обычный левый клик — SPA-переход (без перезагрузки страницы). + // Ctrl/Cmd/Shift/среднюю кнопку — не трогаем, пусть браузер сам + // откроет в новой вкладке по href. + if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) { + return; + } + e.preventDefault(); + navigate({ mode: 'approve', formKey: r.formKey, itemId: r.id }); + }} + > + {r.title || `#${r.id}`} + + + {variant === 'approval' && ( + + {[r.authorName, r.authorEmail].filter(Boolean).join(' · ') || '—'} + + )} + {formatDate(r.created)} + {variant === 'own' && ( + {r.status || '—'} - )} - -
  • + + )} + +); + +const RequestsTable: React.FC<{ rows: IMyRequest[]; variant: 'own' | 'approval' }> = ({ rows, variant }) => ( + + + + + + {variant === 'approval' && } + + {variant === 'own' && } + + + + {rows.map((r) => ( + + ))} + +
    ТипНазваниеАвторДатаСтатус
    ); // Постраничная навигация: номера страниц + вперёд/назад. При большом @@ -158,11 +179,7 @@ const PendingSection: React.FC<{ rows: IMyRequest[] }> = ({ rows }) => { return ( <> - + ); @@ -220,11 +237,7 @@ const OwnSection: React.FC<{ context: WebPartContext; types: IRequestType[]; que return ( <> - + );