# Заявки на транспорт

<!-- wb-memory.v1
{
  "schemaVersion": "wb-memory.v1",
  "id": "screen.transport-requests",
  "kind": "screen",
  "title": "Заявки на транспорт",
  "lifecycle": "active",
  "authority": "canonical",
  "areaId": "area.external-logistics",
  "routes": ["/transport-requests"],
  "links": [
    { "type": "uses-component", "targetId": "component.sidebar", "sourceRefIds": ["S1"] },
    { "type": "uses-component", "targetId": "component.main-container", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.button", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.header-widget", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.tab-horiz-row", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.tab-standard", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.filter-row", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.filter-chip", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.button-flat", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.filter-dropdown-select", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.filter-dropdown-range", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.table", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.table-header", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.table-cell", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.empty-state", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.line-clamp-popup", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.modal", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.toast", "sourceRefIds": ["S2"] },
    { "type": "uses-component", "targetId": "component.tooltip", "sourceRefIds": ["S2"] }
  ],
  "sourceRefs": [
    {
      "id": "S1",
      "kind": "code",
      "authority": "implementation",
      "path": "src/app/design-system/organisms/sidebar/sidebar.component.ts",
      "status": "verified"
    },
    {
      "id": "S2",
      "kind": "code-map",
      "authority": "canonical",
      "path": "specs/ux/components/inventory.json",
      "status": "verified"
    },
    {
      "id": "S3",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=16970-22753",
      "status": "verified"
    },
    {
      "id": "S4",
      "kind": "code",
      "authority": "implementation",
      "path": "src/app/app.routes.ts",
      "status": "verified"
    },
    {
      "id": "S5",
      "kind": "test",
      "authority": "evidence",
      "path": "src/app/app.component.spec.ts",
      "status": "verified"
    },
    {
      "id": "S6",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17007-141048",
      "status": "verified"
    },
    {
      "id": "S7",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17034-12382",
      "status": "verified"
    },
    {
      "id": "S8",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17034-12383",
      "status": "verified"
    },
    {
      "id": "S9",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17034-12388",
      "status": "verified"
    },
    {
      "id": "S10",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17034-12389",
      "status": "verified"
    },
    {
      "id": "S11",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17007-142972",
      "status": "verified"
    },
    {
      "id": "S12",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17007-141799",
      "status": "verified"
    },
    {
      "id": "S13",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17034-11984",
      "status": "verified"
    },
    {
      "id": "S14",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17034-12560",
      "status": "verified"
    },
    {
      "id": "S15",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17034-18928",
      "status": "verified"
    },
    {
      "id": "S16",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/EO9tuCsqwuHL8cZ4Eb2psR/?node-id=3910-389",
      "status": "verified"
    },
    {
      "id": "S17",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/EO9tuCsqwuHL8cZ4Eb2psR/?node-id=9036-58781",
      "status": "verified"
    },
    {
      "id": "S18",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/EO9tuCsqwuHL8cZ4Eb2psR/?node-id=19120-65078",
      "status": "verified"
    },
    {
      "id": "S19",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17034-24286",
      "status": "verified"
    },
    {
      "id": "S20",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17065-57356",
      "status": "verified"
    },
    {
      "id": "S21",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17065-77149",
      "status": "verified"
    },
    {
      "id": "S22",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17113-98641",
      "status": "verified"
    },
    {
      "id": "S23",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17034-21028",
      "status": "verified"
    },
    {
      "id": "S24",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17065-58399",
      "status": "verified"
    },
    {
      "id": "S25",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17065-77752",
      "status": "verified"
    },
    {
      "id": "S26",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17049-27992",
      "status": "verified"
    },
    {
      "id": "S27",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17065-58167",
      "status": "verified"
    },
    {
      "id": "S28",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17065-77379",
      "status": "verified"
    },
    {
      "id": "S29",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17113-98863",
      "status": "verified"
    },
    {
      "id": "S30",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17049-25924",
      "status": "verified"
    },
    {
      "id": "S31",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17065-73224",
      "status": "verified"
    },
    {
      "id": "S32",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17065-77630",
      "status": "verified"
    },
    {
      "id": "S33",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17113-105050",
      "status": "verified"
    },
    {
      "id": "S34",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17007-136122",
      "status": "verified"
    },
    {
      "id": "S35",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17034-24275",
      "status": "verified"
    },
    {
      "id": "S36",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17065-58165",
      "status": "verified"
    },
    {
      "id": "S37",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17065-77377",
      "status": "verified"
    },
    {
      "id": "S38",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17113-104658",
      "status": "verified"
    },
    {
      "id": "S39",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17049-34158",
      "status": "verified"
    },
    {
      "id": "S40",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17065-58450",
      "status": "verified"
    },
    {
      "id": "S41",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17113-98635",
      "status": "verified"
    },
    {
      "id": "S42",
      "kind": "figma",
      "authority": "evidence",
      "url": "https://www.figma.com/design/uGBDiLA947AJwkuvpohikQ/?node-id=17113-98864",
      "status": "verified"
    },
    {
      "id": "S43",
      "kind": "code",
      "authority": "implementation",
      "path": "src/app/features/transport-requests/transport-requests.component.ts",
      "status": "verified"
    },
    {
      "id": "S44",
      "kind": "code",
      "authority": "implementation",
      "path": "src/app/features/transport-requests/transport-requests.component.html",
      "status": "verified"
    },
    {
      "id": "S45",
      "kind": "test",
      "authority": "evidence",
      "path": "src/app/features/transport-requests/transport-requests.component.spec.ts",
      "status": "verified"
    }
  ]
}
-->

## Readiness

| Dimension       | Status and evidence                                                                                                                                                    |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Specification   | Документ описывает текущий desktop fixture-прототип с fixed columns, motion, семью ролями, разнообразными fixtures и per-tab states. [S2] [S3] [S39] [S40] [S41] [S42] |
| Figma           | Read-only evidence задаёт role visibility и permissions для «Новых», «В работе», «Ожидают оплаты» и «Архивных». [S39] [S40] [S41] [S42]                                |
| Local prototype | Route `/transport-requests` реализует fixture-сценарий и текущий UI Kit alignment для modal, toast, tabs, filters, table и Sidebar. [S1] [S4] [S16] [S17] [S18]        |
| Verification    | Предыдущие 78 focused tests и Browser QA экрана предшествуют D-038 и его default `m` rail. D-038 добавляет отдельную component-focused и browser QA проверку текущей геометрии контейнера. [S5] |

`lifecycle: active` означает, что документ описывает текущий локальный
Angular-прототип. Production-интеграция не реализована.

## Current layout and table behavior

### Layout and table geometry

- Весь обычный контент экрана — Header Widget, вкладки, Filter Row, таблица и
  экранные состояния — использует один центрированный default `m` rail с
  максимальной шириной `1440px` внутри Main Container. App shell передаёт
  `size="m"` и `[verticalScroll]="false"`.
- Table, включая Filter Row, Action Bar и scroll frame, не выходит за границы
  этого rail. В contained-scroll режиме нативный gutter для scrollbar остаётся
  внутри этого же Table viewport и не меняет его внешние inline-границы;
  горизонтальный overflow остаётся внутри Table viewport.
- Во вкладке «Предварительные» колонки `ID` и действий передают
  `fixedColumn: false`; все колонки прокручиваются вместе с таблицей.
- Во вкладках «Новые», «В работе», «Ожидают оплаты» и «Архивные» `ID / статус`
  и следующая за ней колонка `Тип заявки` образуют последовательную fixed-группу
  слева, а колонка действий фиксируется справа. Table рассчитывает `fixedOffset`
  как сумму ширин предыдущих fixed columns и закрепляет группы через нативные
  `inset-inline-start`/`inset-inline-end`. Boundary separators определяются из
  `fixedColumn: true`; scroll-driven transforms и signals не используются.

### Filters per tab

- Компоновка и набор фильтров подтверждены отдельным Figma-состоянием. [S6]
- Фильтр `Тип заявки` показывается во вкладках «Предварительные», «Новые», «В
  работе» и «Архивные», использует multiselect и включает действие «Выбрать все»
  через `[showSelectAll]="true"`. «Предварительные» используют три значения,
  остальные показанные вкладки — полный каталог из 11 значений. Во вкладке
  «Ожидают оплаты» control скрыт, а fixtures имеют тип «Коммерческая».
- Постоянный фильтр `ID` использует searchable single-select по ID заявки.
- Только вкладка «Новые» показывает switch «Показать просроченные»; он оставляет
  строки со статусом «Просрочена» и сбрасывает visible limit к первой порции.
- Через `+ Фильтр` добавляется per-tab каталог из 10, 12, 11 или 12 controls,
  перечисленный ниже. Добавленный фильтр исчезает из списка доступных и может
  быть удалён из Filter Row.
- Каждая из пяти вкладок хранит собственные applied values и набор видимых
  optional filters. Переключение вкладки восстанавливает её последнее состояние
  и не переносит значения из другой вкладки.
- `Сбросить фильтры` очищает значения постоянных и optional filters только в
  активной вкладке и очищает `visibleOptional`. Добавленные controls исчезают,
  а полный per-tab каталог снова доступен в меню `+ Фильтр`. Состояния других
  вкладок сохраняются. Reset disabled, когда значения фильтров активной вкладки
  уже находятся в исходном состоянии.
- Фильтрация применяется к данным активной вкладки. Нулевая выдача после
  применения фильтра выбирает filtered-empty, а отсутствие записей до фильтрации
  выбирает обычный empty.

### Sorting and loading more

- В «Предварительных» sortable остаются `ID` и `Дата создания`; в остальных
  вкладках к ним добавляется `Дата подачи машины`. Исходный active sort —
  `Дата создания` по убыванию. Пользовательский sort применяется только к данным
  активной вкладки.
- Список использует infinite scroll без Pagination: сначала показывает 18 строк,
  а при приближении Table viewport к концу синхронно добавляет
  следующую fixture-порцию из 12 строк без потери applied filters, active sort
  или фокуса. После отображения всех fixtures подгрузка прекращается.
- Длинное значение `Маршрут` остаётся компактным. Существующий Line Clamp Popup
  открывается только при фактическом клиппинге и показывает полный текст,
  сохраняя существующую pointer-only accessibility boundary компонента. [S15]

### States

- `loading`: вместо Table и Filter Row показывается screen-level loader с
  доступным именем «Загрузка заявок». [S11]
- `empty`: данных активной вкладки нет до применения фильтров; показывается
  обычный Empty State. [S12]
- `filtered-empty`: applied filters дали ноль строк; показывается вариант
  `filter-result` с отдельным title активной вкладки и caption «Попробуйте
  изменить фильтры», а Filter Row и reset остаются доступны. Table viewport
  скрывает overflow, scrollbar и divider под текстом. [S13]
- `load-error`: initial load завершился ошибкой; вместо строк показывается
  error-state с повторным запросом. Applied filter state активной вкладки не
  теряется. [S14]
- Состояния взаимоисключающие; modal и toast являются overlay/feedback поверх
  последнего успешного списка и не превращаются в состояние таблицы.

### Deletion and feedback

- Выбор «Удалить» для строки открывает подтверждающий Modal, связанный с
  выбранной заявкой; до подтверждения данные не меняются. [S7] [S8]
- Отмена, Escape и допустимое закрытие modal сохраняют строку. Подтверждение
  выполняется Button с вариантом `danger` и запускает screen-owned fixture-
  результат удаления.
- При success строка удаляется из данных активной вкладки, modal закрывается и
  показывается success Toast. [S9]
- При error строка остаётся, modal закрывается и показывается error Toast с
  понятным текстовым результатом. [S10]
- Toast объявляет результат через существующие `status`/`alert` semantics,
  закрывается только по своему screen-owned состоянию и не полагается на цвет.

## Fixed header and table viewport

Текущая вертикальная композиция экрана:

- Header Widget с заголовком и вкладками, а также Filter Row остаются неподвижны
  внутри Main Container.
- Вертикальный overflow получает только ограниченный viewport строк Table.
  Заголовок колонок остаётся sticky в верхней границе этого viewport, а
  горизонтальная прокрутка по-прежнему принадлежит Table.
- Infinite scroll слушает viewport строк Table и добавляет следующую fixture-
  порцию при приближении к его нижней границе.
- Экран передаёт `[verticalScroll]="false"` в Main Container и
  `[containedScroll]="true"` в Table. Table viewport имеет `role="region"`,
  `tabindex="0"` и доступное имя таблицы.

## UI Kit alignment

Текущая M-002 интеграция:

- Delete Modal сохраняет title как имя диалога, а поясняющий текст переносит из
  `descriptionText` в обычный `<p>`, проецируемый в `.wbl-modal__content`.
  Inputs `description` и `descriptionText` не используются. Footer по-прежнему
  содержит отмену и danger-подтверждение. [S7] [S8]
- Success/error Toast шириной 372px соответствует UI Kit node `3910:389`.
  Появление занимает 300ms через `--duration-slow` (`Fade-in` + `Slide-right`),
  закрытие — 200ms через `--duration-toast-dismiss` (`Fade-out` +
  `Slide-left`). Toast остаётся в DOM до `animationend`, после которого
  существующий `dismiss` очищает screen-owned состояние. [S9] [S10] [S16]
- Toast расположен на 16px от левого края content-области рядом с Sidebar и на
  32px от нижней границы экрана.
- Ширина каждой вкладки и всей строки остаётся стабильной при переключении
  active/inactive; label, badge и соседние вкладки не сдвигаются.
- Disabled reset рендерится как disabled Button Flat с `variant='primary'`.
  Disabled token — graphite-300 (`#c4c4d4`). Дополнительные 8px
  `margin-inline-end` дают итоговый интервал 16px до следующего divider.
- Active Filter Chip без applied value/count показывает только label, без
  двоеточия. Двоеточие остаётся частью заполненного состояния.
- Sort affordance в Table Header получает Tooltip «Сортировать» для hover и
  keyboard focus. [S17]
- Table viewport и Sidebar navigation используют нативный 4px UI Kit scrollbar:
  прозрачный track и pill-radius thumb tertiary `#c4c4d4`; декоративный Table
  rail удалён. Sidebar thumb прозрачен в покое и становится видимым при hover
  или `focus-within`, не меняя scroll geometry. [S17] [S18]
- Collapse-кнопка Sidebar получает Tooltip «Свернуть Ctrl B» / «Развернуть
  Ctrl B» на Windows/Linux или «Свернуть ⌘ B» / «Развернуть ⌘ B» на macOS.
  Shortcut переключает то же controlled состояние Sidebar и игнорируется в
  input, textarea, select и editable content.

## Tab states and overflow refinement

- Четыре дополнительные выбранные вкладки сверяются с отдельными Figma-узлами:
  «Новые» — `17034:24286`, «В работе» — `17065:57356`, «Ожидают оплаты» —
  `17065:77149`, «Архивные» — `17113:98641`. Эти refs задают только визуальное
  состояние и содержимое соответствующей вкладки. Интеграция остаётся fixture-
  only и сохраняет общий infinite scroll. [S19] [S20] [S21] [S22]

| Вкладка           | Текущие колонки и ширины                                                                                                                                                                                                                 |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| «Предварительные» | `ID` 112px; `Тип заявки` 196px; `Маршрут` `minmax(376px, 1fr)`; `Ответственный` 244px; `Дата создания` 160px; действия 68px. При rail 1156px таблица занимает всю ширину.                                                                |
| «Новые»           | `ID / статус` 136px; `Тип заявки` 224px; `Маршрут` 360px; `Ответственный` 248px; `Детали` 304px; `Норматив` 196px; `Дата подачи машины` 168px; `Перевозчик / водитель` 272px; `ТС / прицеп` 260px; `Дата создания` 156px; действия 68px. |
| «В работе»        | `ID / статус` 208px; те же common columns от `Тип заявки` до `ТС / прицеп`; `Транспортное задание` 184px; `Отгрузка` 184px; `Дата создания` 156px; `Дата взятия в работу` 172px; действия 68px.                                          |
| «Ожидают оплаты»  | `ID / статус` 176px; `Тип заявки` 144px; common columns от `Маршрут` до `ТС / прицеп`; `Транспортное задание` 184px; `Дата создания` 156px; `Дата взятия в работу` 172px; действия 68px.                                                 |
| «Архивные»        | `ID / статус` 152px; `Тип заявки` 224px; common columns от `Маршрут` до `ТС / прицеп`; `Транспортное задание` 184px; `Отгрузка` 148px; `Дата создания` 156px; `Дата взятия в работу` 172px; `Дата закрытия` 156px; действия 68px.        |

- Во всех расширенных вкладках `Детали` показывает primary
  `Груз: {cargo} · Расстояние: {distance}` и description `Ставка: {rate}`.
  Для `Коммерческая` description продолжается как
  ` · Грузовладелец: {cargoOwner}`.
- `Норматив` показывает primary `Время: {duration}` и description
  `Тип маршрута: {routeType}`. Во вкладке «Предварительные» колонок `Детали` и
  `Норматив` нет.

- В колонке `ID / статус` Badge показывается под обычным ID, когда fixture-
  статус задан. «Новые» использует «Просрочена»/error; «В работе» — «В работе»/
  info, «Едет на погрузку»/warning, «Просрочена»/error, «Осуществляется
  доставка»/success и «На погрузке»/warning; «Ожидают оплаты» — «Ожидает
  подтверждения»/info и «Ожидает оплаты»/warning; «Архивные» — «Закрыта»/
  success и «Отменена»/error.
- В contained/paginated Table scroll frame является flex-контейнером с
  `overflow: visible` и без `padding-inline-end`. Viewport использует
  `inline-size: 100%`, `overflow: auto` и `scrollbar-gutter: stable`; native
  scrollbar gutter резервируется внутри rail, без правого внешнего продолжения.
- Sidebar menu использует `overflow-x: hidden` и внешний gutter `--space-300`
  через равные отрицательный margin и padding. Collapsed Sidebar не создаёт
  horizontal scroll; тот же `/logo/Logo.svg` остаётся на x=12, а wrapper клипует
  только текст логотипа.
- Collapse Tooltip не содержит разделительную интерпункцию. На macOS он
  показывает «Свернуть ⌘ B» / «Развернуть ⌘ B», на Windows/Linux — «Свернуть
  Ctrl B» / «Развернуть Ctrl B»; между modifier и `B` используется thin space
  U+2009.
- Поясняющий `<p>` в delete Modal использует
  `--typography-body-horse` regular без bold.

Все правила этого раздела реализованы локально; они не добавляют backend или
production integration.

## Tab transition, fixed columns, and row actions

Текущая M-002 реализация использует лёгкое, едва заметное переключение вкладок:

- визуальные состояния Tab Standard меняют цвет текста, underline и Badge за
  `--duration-fast` с `--ease-out`;
- обёртка содержимого таблицы при смене вкладки переходит только от
  `opacity: 0.9` к `opacity: 1` за `--duration-fast` с `--ease-standard`;
- переход не сдвигает соседние вкладки, Header Widget, Filter Row, sticky header,
  fixed columns или action column и не блокирует keyboard/pointer interaction;
- при смене вкладки Table сохраняет внешнюю геометрию, а horizontal scroll
  viewport сбрасывается в начало;
- при `prefers-reduced-motion: reduce` transition вкладки и animation содержимого
  полностью отключаются; выбранное состояние и содержимое заменяются сразу.

Fixed-конфигурация поколоночная и зависит от активной вкладки:

- «Предварительные» не фиксируют ни одной колонки;
- «Новые», «В работе», «Ожидают оплаты» и «Архивные» фиксируют `ID / статус` и
  `Тип заявки` слева, а действия справа;
- Table не получает screen-specific ID колонок по умолчанию: экран передаёт
  конфигурацию активной вкладки через существующий `WblTableColumn.fixedColumn`.

Состав действий строк реализован по отдельным read-only refs и выбранной роли.
Текстовые команды передаются с `overflow: true`. На вкладках «Новые», «В
работе» и «Ожидают оплаты» строка с комментарием показывает рядом с More trigger
direct icon-only действие «Комментарий» с `variant: 'flat-primary'`, иконкой
`message-lines`, `showLabel: false` и полным текстом комментария в
`tooltipText`. Tooltip доступен по hover/focus; `label` остаётся accessible name:

- «Предварительные»: overflow «Редактировать» и «Удалить»; Comment нет.
- «Архивные»: только overflow «Посмотреть детали»; Comment нет, архив
  read-only для всех ролей.
- «Новые»: старший логист видит overflow «Удалить» для просроченной строки; для
  остальных — «Взять в работу», отделённое «Редактировать», «Удалить».
  Поставщик и главный поставщик видят «Удалить» для просроченной строки, иначе
  «Взять в работу». Менеджер продаж видит «Посмотреть детали». Администратор
  видит «Создать основную заявку» для автоматической заявки, иначе «Посмотреть
  детали». Direct Comment добавляется в любом из этих вариантов только при
  непустом комментарии строки. [S23]
- «В работе»: «Снять перевозчика» доступно только старшему логисту для
  автоматической заявки не в статусах «На погрузке» и «Осуществляется доставка»;
  direct Comment добавляется при непустом комментарии. [S24]
- «Ожидают оплаты»: всегда доступно overflow «Посмотреть детали»; direct Comment
  добавляется при непустом комментарии;
  «Скопировать» добавляется для статуса «В работе», а «Снять перевозчика» в этом
  статусе видит только старший логист. [S25]

Table Cell передаёт `separatorBefore` в Dropdown, поэтому separator перед
«Редактировать» остаётся частью screen-owned массива действий. Команды являются
fixture-заглушками, кроме уже описанного удаления; backend-навигация и mutations
не добавлены.

## Sorting, filters, request types, and table scrollbar

Текущий локальный fixture-сценарий реализует следующие Figma-аннотации:

### Sorting

- Во вкладках «Новые», «В работе», «Ожидают оплаты» и «Архивные» sortable
  становятся `ID`, `Дата создания` и `Дата подачи машины`. [S26] [S27] [S28]
  [S29]
- `ID` сравнивается через существующий `localeCompare` с `numeric: true`.
  Значения формата `DD.MM.YYYY HH:mm` распознаются Table и сравниваются
  хронологически, поэтому обе даты не зависят от строкового порядка.
- Исходный sort для этих вкладок — `Дата создания` по убыванию.
- Table Header сохраняет controlled `aria-sort`, текущий cycle и Tooltip
  «Сортировать»; конкретный comparator и набор sortable columns остаются
  ответственностью Table и экрана.
- Поведение «Предварительных» остаётся без изменений.

### Filter availability and state

- Filter Row хранит applied values и controlled `openedFilterId` отдельно для
  каждой вкладки. `Тип заявки` (когда показан) и `ID` — `pinned` controls;
  каждый пункт add-filter — `optional`. Семантическое действие pinned control
  сбрасывает только его screen-owned значение; действие optional control
  очищает его значение и скрывает control.
- Меню добавления фильтра исключает уже показанные controls, открывает новый
  optional control и использует полный каталог первой и второй итераций:

| Вкладка          | Количество | Добавляемые фильтры                                                                                                                                   |
| ---------------- | ---------: | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| «Новые»          |         10 | `Маршрут`, `Номер ТС`, `Статус`, `Точка отправления`, `Точка назначения`, `Ответственный`, `Грузовладелец`, `Перевозчик`, `Номер прицепа`, `Водитель` |
| «В работе»       |         12 | набор «Новых» плюс `Транспортное задание` и `Отгрузка`                                                                                                |
| «Ожидают оплаты» |         11 | набор «В работе» без `Отгрузка`                                                                                                                       |
| «Архивные»       |         12 | тот же набор, что у «В работе»                                                                                                                        |

- «Показать просроченные» остаётся отдельным switch вкладки «Новые» и не
  считается добавляемым dropdown-filter.
- `Статус` — multiselect; `Маршрут` — searchable multiselect. Остальные новые
  поля — searchable single select. Все options строятся из статических fixtures
  активной вкладки.
- Applied filters фильтруют только статические fixtures. При закрытии пустого
  optional control он удаляется. «Сбросить фильтры» очищает значения,
  `visibleOptional` и `openedFilterId` текущей вкладки, возвращая полный
  каталог в add-filter menu; состояние остальных вкладок сохраняется.

### Request types

- «Предварительные» допускают только `Мебель`, `Внешний поставщик` и
  `ТМЦ склада`; другие типы в этой вкладке не показываются. [S34]
- «Новые», «В работе» и «Архивные» используют 11 значений: `Стандартный`,
  `Стандартный новый`, `Автоматическая`, `Мебель`, `Внешний поставщик`,
  `Прочее`, `ТМЦ склада`, `Технический ПЛ`, `Перегон ТС`,
  `Обслуживание или ремонт ТС`, `Коммерческая`. [S35] [S36] [S38]
- «Ожидают оплаты» содержит только тип `Коммерческая`; скрытый в текущей
  версии type-filter не добавляется обратно только ради одного значения. [S37]
- Option sets задаёт экран. Filter Dropdown Select не хранит глобальный каталог
  типов и не переносит выбор между вкладками.

### Contained table scrollbar

- В contained-scroll Table `.wbl-table__scroll-frame` использует flex,
  `overflow: visible` и не резервирует внутренний padding. Viewport имеет
  `inline-size: 100%`, `overflow: auto` и `scrollbar-gutter: stable`.
- Нативный vertical scrollbar резервирует место внутри Table viewport: Table,
  scroll frame и viewport имеют те же внешние inline-границы, что и выбранный
  Main Container rail. Gutter не создаёт внешнего продолжения и не перекрывает
  header, cells или действия строк. Вертикальная и горизонтальная прокрутка
  принадлежат одному доступному Table viewport; новый публичный input не
  добавлен.

## Fixed columns, interaction polish, roles, and fixtures

### Table geometry and feedback

- Зафиксированные слева/справа колонки остаются визуально неподвижны при
  горизонтальной прокрутке данных. Table рассчитывает `fixedOffset` из ширин
  предыдущих fixed columns и нативно закрепляет их через
  `inset-inline-start`/`inset-inline-end`; scroll-driven transforms/signals не
  используются. Browser-проверка при `scrollLeft` 0 и 1200 сохраняет левые
  колонки на x=92–228 и x=228–452, правую — на x=1177–1249. Новый public API не
  добавлен.
- Переключение вкладки, роли, состояния или набора row actions не меняет внешний
  размер Table viewport, позиции fixed columns и ширину action column. Action
  column во всех вкладках равна 68px. Ячейка выравнивает группу вправо, использует
  8px inline padding и gap 4px: одна кнопка остаётся у правого края, а две
  занимают `24 + 4 + 24 + 16 = 68px`.
- Success/error Toast находится на 16px от левого и на 32px от нижнего края
  viewport. Это screen-owned placement, которое не меняет Toast API или его
  retained-exit lifecycle.
- Каждая вкладка имеет собственные воспроизводимые `loading`, `empty`, `error`
  и `filtered-empty` состояния. Они применяются к выбранной вкладке с учётом
  активной роли; в `filtered-empty` под текстом результата нет divider.

| Вкладка           | Loading                                 | Empty                                                                                                                          | Filtered empty                          | Error                                           |
| ----------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------- | ----------------------------------------------- |
| «Предварительные» | «Загружаем предварительные заявки...»   | «Предварительных заявок пока нет»; «Чтобы создать предварительную заявку, нажмите на кнопку вверху страницы „Создать заявку“». | «Предварительные заявки не найдены.»    | «Не удалось загрузить предварительные заявки»   |
| «Новые»           | «Загружаем новые заявки...»             | «Новых заявок пока нет»; «Новые заявки появятся здесь после создания.»                                                         | «Новые заявки не найдены.»              | «Не удалось загрузить новые заявки»             |
| «В работе»        | «Загружаем заявки в работе...»          | «Заявок в работе пока нет»; «Взятые в работу заявки появятся здесь.»                                                           | «Заявки в работе не найдены.»           | «Не удалось загрузить заявки в работе»          |
| «Ожидают оплаты»  | «Загружаем заявки, ожидающие оплаты...» | «Заявок, ожидающих оплаты, пока нет»; «Заявки появятся здесь после завершения перевозки.»                                      | «Заявки, ожидающие оплаты, не найдены.» | «Не удалось загрузить заявки, ожидающие оплаты» |
| «Архивные»        | «Загружаем архивные заявки...»          | «Архивных заявок пока нет»; «Закрытые и отменённые заявки появятся здесь.»                                                     | «Архивные заявки не найдены.»           | «Не удалось загрузить архивные заявки»          |

У всех filtered-empty состояний caption «Попробуйте изменить фильтры», у error
— «Проверьте подключение к интернету и попробуйте ещё раз.». Loading не имеет
caption.

### Cell and sort motion

- Line Clamp Popup смещается относительно origin на `-1px` по inline-start и
  block-start, совпадает border с верхней границей ячейки и принимает ширину
  originating Table Cell. Enter/leave используют opacity и translate за 140ms;
  при reduced motion переход отключается без изменения pointer-only semantics.
- Sort control всегда резервирует место. Иконка появляется через opacity/scale
  на hover или в sorted-состоянии, а `arrow-up` поворачивается на 180 градусов
  для descending; оба перехода используют `--duration-fast` и
  `--ease-standard`, отключаются при reduced motion и не задерживают `aria-sort`
  или сортировку.

### Actions and fixture content

- В role/status action matrix «Комментарий» является optional per-row direct
  icon-only action с `{ id: 'comment', label: 'Комментарий',
variant: 'flat-primary', iconName: 'message-lines', showLabel: false,
tooltipText: <полный текст комментария> }`. Он доступен только во вкладках
  «Новые», «В работе» и «Ожидают оплаты», показывает Tooltip по hover/focus и не
  открывает production route или mutation. Fixtures содержат разные длинные
  комментарии и строки без комментария.
- Статические fixture-наборы разнообразны по типам, статусам, маршрутам,
  ответственным, перевозчикам, водителям, ТС, прицепам и значениям документов;
  часть строк намеренно не имеет назначения, отгрузки, перевозчика, водителя,
  ТС или прицепа.
- Для commercial row «Детали» показывает description
  `Грузовладелец: <название>` через существующую primary/description композицию
  Table Cell.

### Role switcher island and visibility matrix

Role switcher island — screen-only fixture control для проверки матрицы семи
ролей. `aside` имеет доступное имя «Роль для просмотра интерфейса», показывает
выбранную роль и атомарно обновляет tabs, rows, filters, states и actions. Он не
моделирует production authentication, permissions API или persistence.

- `supplier` и `main-supplier` имеют одинаковые права на данные: видят «Новые», «В работе»
  и «Архивные», не видят «Предварительные» и «Ожидают оплаты», а строки,
  забранные другим перевозчиком, исключаются. В архиве остаются только доступные
  заявки своего перевозчика. [S39] [S40] [S42]
- `sales-manager` видит только commercial rows и действие «Посмотреть детали»;
  вкладка «Ожидают оплаты» скрыта. В архиве некоммерческие заявки не
  показываются. [S39] [S40] [S42]
- `senior-logistic` видит все вкладки и оба статуса во вкладке «Ожидают оплаты».
  Он может удалить любую «Новую» заявку до взятия в работу, включая чужую,
  commercial и основную автоматическую. Во вкладке «В работе» может снять
  перевозчика только у основной автоматической заявки в разрешённом статусе;
  после взятия удаление недоступно. Архив read-only. [S39] [S40] [S41] [S42]
- `administrator` видит все вкладки и строки. Для новой автоматической заявки
  он получает «Создать основную заявку», для другой новой — «Посмотреть
  детали»; universal delete старшего логиста не получает. [S39] [S40]
- Во вкладке «Ожидают оплаты» `senior-commercial-logistic` видит только статус
  «В работе», специалист по документам — только «Ожидает оплаты», старший логист
  — оба статуса. Для первых двух ролей filter `Статус` скрыт; `supplier`,
  `main-supplier` и менеджер продаж не видят вкладку. [S41]
- `senior-commercial-logistic` видит «В работе», «Ожидают оплаты» и «Архивные»;
  `document-specialist` — «Ожидают оплаты» и «Архивные». Архив всегда read-only.
  [S42]

Кнопка «Создать заявку» доступна `senior-logistic`, `main-supplier`,
`sales-manager` и `administrator`. По умолчанию и при неизвестном `role`
выбирается `senior-logistic`; при недоступной для новой роли текущей вкладке
экран выбирает первую разрешённую. Во вкладке «Ожидают оплаты» filter `Статус`
скрыт для `senior-commercial-logistic` и `document-specialist`.

## Purpose

Экран позволяет открыть раздел «Заявки на транспорт» внутри
«Логистика внешняя» и просмотреть записи в плотной desktop-таблице. Figma
подтверждает поля ID, тип заявки, маршрут, ответственного и дату создания;
бизнес-сценарии требуют отдельного продуктового контракта. [S1] [S3]

## Source and Route

- Визуальный источник: Figma file `uGBDiLA947AJwkuvpohikQ`, node
  `16970:22753`. Узел прошёл свежую проверку через design context, variables и
  screenshot. [S3]
- Точка входа: существующий пункт `external-logistics-transport-requests`
  («Заявки на транспорт») внутри раздела «Логистика внешняя». [S1]
- Route: `/transport-requests`.
- Управляемые fixture-состояния доступны на
  `/transport-requests?state=loading`, `?state=empty`,
  `?state=filtered-empty` и `?state=error`; `?tab=<TabId>` и `?role=<RoleId>`
  выбирают вкладку и роль, поэтому параметры можно объединять для проверки
  per-tab copy и role-filtered data. Ошибочный результат удаления — на
  `/transport-requests?deleteResult=error`.
- Source files:
  `src/app/features/transport-requests/transport-requests.component.ts`,
  `.html`, `.scss` и `.spec.ts`. [S4] [S5]
- Выходы в карточку, форму редактирования или другой экран не определены.

## Primary Scenario

Текущий сценарий fixture-версии:

1. Пользователь выбирает «Заявки на транспорт» в «Логистика внешняя».
2. Shell показывает заголовок «Заявки на транспорт», primary action «Создать
   заявку», вкладки «Предварительные», «Новые», «В работе», «Ожидают оплаты» и
   «Архивные», Filter Row и таблицу. По умолчанию выбрана вкладка
   «Предварительные» со счётчиком 23. [S3]
3. Filter Row показывает постоянные фильтры «Тип заявки» и «ID» там, где они
   применимы, позволяет добавить per-tab каталог optional filters и фильтрует
   fixtures активной вкладки.
4. Доступные действия зависят от вкладки и статуса строки согласно текущей
   action-матрице выше. «Удалить» запускает подтверждение и success/error
   feedback; остальные команды остаются визуальными fixture-заглушками.

## Alternate Scenarios

- Экран открывается по прямому URL `/transport-requests` и через пункт Sidebar.
- Действия строки зависят от вкладки, fixture-статуса и одной из семи ролей по
  текущей матрице выше; optional direct «Комментарий» может оставаться
  единственным действием строки на трёх рабочих вкладках.
- Переключение вкладки восстанавливает отдельное состояние её фильтров.
- Query-параметры `state`, `tab`, `role` и `deleteResult` выбирают
  воспроизводимые fixture-сценарии для QA; неизвестные значения возвращают
  безопасные значения по умолчанию.

## States, Errors, and Edge Cases

- Реализованы взаимоисключающие состояния ready, loading, empty,
  filtered-empty и load-error. Access denied и production network semantics не
  определены.
- Длинные значения и горизонтальный overflow должны оставаться внутри Table.
  Текущая вкладка «Предварительные» использует ID 112px, тип заявки 196px,
  маршрут `minmax(376px, 1fr)`, ответственного 244px, дату создания 160px и
  действия 68px. Screen-owned preliminary class задаёт Table inner, header и
  rows `inline-size`/`min-inline-size: 100%`, поэтому таблица заполняет rail без
  пустой области и ненужного horizontal overflow. Дата создания отсортирована
  по убыванию. [S3]
- Действие «Удалить» имеет danger-семантику и отдельное доступное имя; fixture-
  строка меняется только после подтверждения в Modal и успешного результата.

## Data and Integration Boundary

- Данные — статические fixtures для визуального handoff; первая порция содержит
  18 строк, следующая — 12.
- Backend API, загрузка, мутации, сохранение, права, production navigation и
  мобильная адаптация не входят в текущий контракт.
- Вкладка «Предварительные» использует компактный набор `ID`, `Тип заявки`,
  `Маршрут`, `Ответственный`, `Дата создания` и действия. Остальные вкладки
  используют точные расширенные наборы выше и status Badge под ID. Все строки
  остаются статическими fixtures. [S3] [S19] [S20] [S21] [S22]
- Расширенные вкладки сохраняют реальную `max-content` ширину Table inner и grid
  rows. Для «Предварительных» screen-owned class задаёт inner/header/rows
  `inline-size` и `min-inline-size: 100%`.
- Filter Row реализован существующей композицией `component.filter-row` с
  projected select-контролами, добавлением optional filters и reset активной
  вкладки. Поиск, switches, column settings и more-actions скрыты; download-
  action остаётся визуальной заглушкой.
- Figma показывает в action-cell один trigger `more-vert`. Table Cell
  поддерживает явный `overflow`, а конкретный набор меню зависит от вкладки и
  статуса согласно action-матрице выше. [S2] [S3] [S23] [S24] [S25]

## D-039 Filter Row behavior

The current fixture implementation uses the lifecycle contract above. Changing
the active tab keeps each tab's filter values and visible optional controls
separate; reset applies only to the active tab. These rules do not add a backend,
persistence, or production permissions contract. [S43] [S44] [S45]

## Components and Accessibility

- [Sidebar](../components/organisms/sidebar.md) предоставляет существующую
  точку входа; App shell связывает её с маршрутом и показывает целевой экран со
  свёрнутым Sidebar, как в подтверждённом Figma-состоянии. [S1] [S3] [S4]
- [Main Container](../components/atoms/main-container.md) сохраняет общий
  desktop-rail и делегирует вертикальную прокрутку Table viewport на этом
  экране.
- [Header Widget](../components/organisms/header-widget.md) показывает H1,
  primary action «Создать заявку» и пять подтверждённых вкладок со счётчиками
  23, 43, 54, 24 и 146. [S3]
- [Table](../components/organisms/table.md) владеет Filter Row, вертикальным и
  горизонтальным overflow viewport строк и отображением typed cells.
- [Filter Row](../components/organisms/wbl-filter-row.md) используется как
  рабочая панель с постоянными и optional filter controls.
- [Table Cell](../components/molecules/table-cell.md) рендерит строковые действия
  через `type: 'actions'`; каждому действию нужен отдельный русский accessible
  name. Для расширенных вкладок тот же компонент рендерит status Badge под ID
  через `badgeText`/`badgeAppearance`. Удаление не должно полагаться только на
  цвет.
- Заголовки колонок должны быть связаны с ячейками, строки иметь устойчивые
  уникальные ID и осмысленные `ariaLabel`, а иконки действий — tooltip и label.

## Related Flows

Межэкранный flow не определён. Переход к редактированию остаётся за пределами
M-002, пока не задан destination. Удаление выполняется внутри текущего экрана
через Modal и Toast и не создаёт отдельного route.

## Verification

Для Angular-прототипа прошли focused tests, включая:

- route и связка Sidebar с shell-state — unit-тестами AppComponent;
- заголовок, пять вкладок и счётчики, отдельное состояние фильтров по вкладкам,
  Type/select-all, optional filters и reset;
- numeric-сортировку ID, chronological-сортировку `DD.MM.YYYY HH:mm` дат,
  initial 18 + batch 12 infinite scroll, отсутствие Pagination, fixedColumn
  opt-out и длинный маршрут;
- loading, empty, filtered-empty, error, подтверждение удаления и success/error
  Toast;
- четыре tab-specific column sets, status Badge под ID, new-only overdue switch,
  скрытый type filter в awaiting-payment, scrollbar geometry внутри rail,
  collapsed Sidebar geometry/tooltip, regular delete body, полные per-tab
  catalogs фильтров и request types.

Browser QA подтвердил готовый экран, фильтр Type с «Выбрать все», optional
filters, текстовые пункты row actions, delete modal/success Toast и управляемые
loading, empty, filtered-empty и error-состояния. Визуальная структура сверена с
точными Figma-узлами [S3] [S6] [S7] [S8] [S9] [S11] [S12] [S13] [S14].

## Open Questions

- Какой route или другой destination должен открывать пункт «Редактировать»?
- Какие production permissions и backend-контракты применяются к загрузке,
  фильтрации и удалению заявок?
- Каковы размер порции, условие окончания списка и retry-контракт для infinite
  scroll после подключения production API?
- Должен ли download-action стандартного Filter Row получить бизнес-обработчик
  или быть скрыт в интеграционной версии?

## Documentation Review

Документация и Angular-прототип обновлены в задаче M-002 по локальным
Git-контрактам и точной пользовательской ссылке на Figma. Figma, tokens и assets
не изменялись. Обновлены feature-код, route, focused tests и Storybook stories.
