diff --git a/docs/guides/frontend/04-PATTERNS.md b/docs/guides/frontend/04-PATTERNS.md
index 947bedbd..c7edbb18 100644
--- a/docs/guides/frontend/04-PATTERNS.md
+++ b/docs/guides/frontend/04-PATTERNS.md
@@ -33,6 +33,7 @@
Для `filter form` дополнительно:
- toolbar и фильтрующий блок лучше держать отдельным feature-компонентом, если page-level файл уже управляет списком, detail modal и compose flow одновременно
+- если filter-toolbar уже соседствует с плотным list shell, сам list shell тоже должен иметь явную anatomy: action rail, content column и отдельные secondary panels вместо одного бесформенного nested block
### Dropdown-like UX
diff --git a/docs/guides/frontend/06-COMPONENT-INVENTORY.md b/docs/guides/frontend/06-COMPONENT-INVENTORY.md
index 1dbcffad..5c6a6c3b 100644
--- a/docs/guides/frontend/06-COMPONENT-INVENTORY.md
+++ b/docs/guides/frontend/06-COMPONENT-INVENTORY.md
@@ -179,7 +179,7 @@
- compose-like form pattern
- detail modal с participant-heavy content
- page-level toolbar/filter block, который вынесен из страницы в feature component
-- dense list row с actions/comments/expandable secondary content
+- dense list row с actions/comments/expandable secondary content, где row anatomy разложена на action rail, content column и отдельные detail/comments panels
- feature container для list shell, который собирает rows + empty state + load more
- отдельный mode-panel для alternate flow вроде swipe-review
- attachment preview modal как отдельный feature block, а не хвост page-level JSX
diff --git a/docs/guides/frontend/07-DEVELOPER-WORKFLOW.md b/docs/guides/frontend/07-DEVELOPER-WORKFLOW.md
index 410c790f..a7edab25 100644
--- a/docs/guides/frontend/07-DEVELOPER-WORKFLOW.md
+++ b/docs/guides/frontend/07-DEVELOPER-WORKFLOW.md
@@ -78,6 +78,7 @@
- то же касается toolbar/filter block и attachment preview, если они уже стали самостоятельными зонами сценария
- router-sync, deep-link opening и dismissable menu state тоже можно выносить в feature hook, если это screen orchestration, а не данные домена
- если внутри одной зоны уже несколько leaf-компонентов, стоит ввести feature container вроде `*Section` или `*Panel`, а не возвращать всё обратно в page-level JSX
+- dense row после такого выноса не должна оставаться одним бесформенным JSX-комком: отдельно собираются action rail, main content и secondary panels вроде details/comments
## 5. Как делать dropdown-поле
diff --git a/docs/guides/frontend/09-FRONTEND-AUDIT-MAP.md b/docs/guides/frontend/09-FRONTEND-AUDIT-MAP.md
index 202161a6..7774968a 100644
--- a/docs/guides/frontend/09-FRONTEND-AUDIT-MAP.md
+++ b/docs/guides/frontend/09-FRONTEND-AUDIT-MAP.md
@@ -13,7 +13,7 @@
| Зона | Статус | Что уже хорошо | Основные проблемы | Рекомендуемый следующий шаг |
| --- | --- | --- | --- | --- |
-| `requests` | `mixed` | compose-настроение, participant-only логика, UI вокруг `can_decide`, compose/list/detail/controls/preview разведены по feature components, screen orchestration вынесена в hook, list/swipe flow собраны в feature containers | visual debt остаётся в отдельных локальных визуальных решениях; зона ещё не стала полным target-state | использовать как референс для разделения orchestration/UI и participant-heavy request flows, затем отдельно чистить локальную визуальную неоднородность |
+| `requests` | `mixed` | compose-настроение, participant-only логика, UI вокруг `can_decide`, compose/list/detail/controls/preview разведены по feature components, screen orchestration вынесена в hook, list/swipe flow собраны в feature containers, dense row приведён к явной anatomy с отдельными detail/comments panels | visual debt сузился, но ещё остаются image warnings и контракт controls block | использовать как референс для разделения orchestration/UI, participant-heavy request flows и anatomy плотной строки, затем добить image/controls cleanup |
| `settings` | `mixed` | сильная surface hierarchy, хорошие primary sections | встречаются custom radii и локальная геометрическая неоднородность | рефакторить карточки и кастомные радиусы без смены общего layout |
| `documents` | `needs refactor` | богатый набор сценариев, detail/upload/comment patterns уже выделены в компоненты | смешение `rounded-md`, `rounded-lg`, `rounded-xl`, разные уровни visual density | сделать отдельный pass по карточкам и metadata/upload flows |
| `equipment` | `needs refactor` | понятные формы и вторичные блоки | много локальных card/form решений, геометрия плавает | после `documents` пройтись по secondary cards и action forms |
@@ -33,7 +33,7 @@
4. `procurement`
5. отдельный audit по `calendar`
-`requests` лучше использовать как референс для compose-настроения, выделения feature-level workspace/list-detail/controls блоков, screen-specific orchestration hooks и feature containers уже сейчас, а не как первую цель глобального переписывания.
+`requests` лучше использовать как референс для compose-настроения, выделения feature-level workspace/list-detail/controls блоков, screen-specific orchestration hooks, feature containers и anatomy плотной строки уже сейчас, а не как первую цель глобального переписывания.
## Как использовать эту карту
diff --git a/frontend/src/app/requests/page.tsx b/frontend/src/app/requests/page.tsx
index 4b4b2a5c..a7077ed0 100644
--- a/frontend/src/app/requests/page.tsx
+++ b/frontend/src/app/requests/page.tsx
@@ -115,7 +115,7 @@ function RequestsPageContent() {
requestMenuRef={screen.requestMenuRef}
requests={h.requests}
setAttachmentPreview={h.setAttachmentPreview}
- setCommentDrafts={h.setCommentDrafts}
+ onSetCommentDraft={h.setCommentDraft}
setDetailsRequest={h.setDetailsRequest}
setRequestMenuOpenId={screen.setRequestMenuOpenId}
toggleComments={h.toggleComments}
diff --git a/frontend/src/components/requests/RequestListItem.tsx b/frontend/src/components/requests/RequestListItem.tsx
index 6334fff7..b00e8cac 100644
--- a/frontend/src/components/requests/RequestListItem.tsx
+++ b/frontend/src/components/requests/RequestListItem.tsx
@@ -5,10 +5,10 @@ import {
statusMeta,
type RequestAttachmentPreview,
} from "@/hooks/useRequestsPage";
-import { displayUserName, formatDate, userProfileLink } from "@/lib/shared";
-import type { Request, RequestComment } from "@/types/api";
+import { displayUserName, formatDate, formatDateTime, userProfileLink } from "@/lib/shared";
+import type { Request, RequestComment, User } from "@/types/api";
import { Ban, ChevronDown, ChevronRight, MessageSquare, Paperclip, Pencil, ThumbsDown, ThumbsUp, Trash2 } from "lucide-react";
-import type { Ref } from "react";
+import type { ReactNode, Ref } from "react";
import { RequestUserBadge } from "./RequestUserBadge";
type RequestListItemProps = {
@@ -38,6 +38,77 @@ type RequestListItemProps = {
rowOpen: boolean;
};
+type RequestMetaFieldProps = {
+ label: string;
+ value: ReactNode;
+};
+
+type RequestAudienceRowProps = {
+ count?: number;
+ currentUserId?: number | null;
+ emptyText: string;
+ label: string;
+ people: User[];
+};
+
+function RequestMetaField({ label, value }: RequestMetaFieldProps) {
+ return (
+