# Дизайн: Доработки админки заказов (маркер цены + быстрые статусы)

**Дата:** 2026-05-28  
**Статус:** Draft

## Контекст

Нужно улучшить UX в админке заказов по двум направлениям:

1. Явно показывать в списке заказов, что требуется подтверждение цены (итоговой стоимости для оплаты).
2. Сделать смену статуса заказа более удобной для администратора.

Ограничения, согласованные в обсуждении:

- Не вводим новый статус заказа для подтверждения цены.
- Используем короткий текст для индикатора.
- Для смены статуса выбираем формат быстрых кнопок доступных переходов (вместо выпадающего списка).

## Цели

- Сократить время на обнаружение заказов, требующих подтверждения цены.
- Упростить и ускорить смену статуса до 1 клика.
- Сохранить существующие API-контракты и логику допустимых переходов.

## Не в рамках этой итерации

- Изменение серверной статусной модели.
- Добавление новых серверных полей или эндпоинтов.
- Массовая смена статусов из таблицы без открытия деталки.
- Редизайн всей таблицы заказов.

## Решение (утвержденный вариант A)

### 1) Маркер в списке заказов

В `client/src/pages/admin-orders/ui/AdminOrdersPage.tsx` добавить короткий бейдж `Цена не подтверждена` для строк, где:

- `status === 'PENDING_PAYMENT'`
- `deliveryType === 'delivery'`
- `deliveryFeeLocked === false`

Размещение: в колонке `ID` рядом с коротким номером заказа (`o.id.slice(-8)`), чтобы не расширять таблицу и чтобы сигнал был виден до открытия деталки.

### 2) Быстрая смена статуса в деталке заказа

В `client/src/features/order-detail/ui/OrderDetailContent.tsx` заменить текущий `Select` "Сменить статус" на набор кнопок быстрых переходов:

- Источник переходов остается прежним: `getAdminNextOrderStatuses(detail.status, detail.deliveryType)`
- Для каждого допустимого статуса рендерится отдельная кнопка
- Клик вызывает текущую мутацию `setAdminOrderStatus` через `statusMut.mutate(next)`

Поведение кнопок:

- Пока мутация выполняется (`statusMut.isPending`) все кнопки отключены
- Если доступных переходов нет — показываем текст `Статус финальный, смена недоступна`
- Для `CANCELLED` использовать визуально менее акцентную кнопку (`outlined`), чтобы снизить риск случайного нажатия

## Архитектурные границы и переиспользование

- Используем существующие данные `deliveryFeeLocked`, `status`, `deliveryType`.
- Правила переходов не дублируем в UI, берем из `getAdminNextOrderStatuses`.
- API слой (`client/src/entities/order/api/admin-order-api.ts`) без изменений.
- React Query инвалидация сохраняется текущая:
  - `['admin', 'orders']`
  - `['admin', 'orders', 'detail']`
  - `['admin', 'orders', 'summary']`

## Поток данных

1. Страница списка получает `items` из `fetchAdminOrders`.
2. Для каждой строки вычисляется `needsPriceApproval`.
3. Если `needsPriceApproval === true`, отображается бейдж `Цена не подтверждена`.
4. В деталке рассчитывается `nextStatuses`.
5. Клик по кнопке статуса вызывает `statusMut`.
6. После успеха инвалидация обновляет список/деталку/summary; маркер в списке исчезает автоматически, когда условие перестает выполняться.

## Обработка ошибок

- Ошибка смены статуса: показать локальный `Alert` в деталке с текстом `Не удалось сменить статус`, дать возможность повторить действие.
- Ошибка загрузки списка: сохранить текущее поведение (`Не удалось загрузить заказы.`).
- Пустой список переходов: показать явное сообщение о финальном статусе.

## Тестирование

Минимальный набор:

1. Unit: проверка условия `needsPriceApproval`.
2. Component (`OrderDetailContent`):
   - рендерит кнопки только допустимых переходов
   - вызывает `setAdminOrderStatus` при клике
   - блокирует кнопки в pending-состоянии
3. Component/Smoke (`AdminOrdersPage`):
   - показывает `Цена не подтверждена` для целевых заказов
   - не показывает бейдж для остальных

## Критерии готовности

- В списке заказов видно короткий маркер `Цена не подтверждена` для релевантных заказов.
- В деталке смена статуса выполняется через быстрые кнопки допустимых переходов.
- Список и деталка синхронизируются после успешной смены статуса.
- Для `CANCELLED` используется менее акцентный стиль кнопки.
- Проходят `npm run lint` и `npm run format:check` в `client`.

## План изменений по файлам

- `client/src/pages/admin-orders/ui/AdminOrdersPage.tsx` — маркер `Цена не подтверждена` в строках списка.
- `client/src/features/order-detail/ui/OrderDetailContent.tsx` — замена select на быстрые кнопки.
- (опционально) `client/src/shared/lib/` — небольшой хелпер `needsPriceApproval`, если нужно переиспользование или unit-тест вне компонента.

## Риски и меры

- Риск перегруза UI в деталке при большом количестве кнопок: низкий, так как число допустимых переходов обычно 1-2.
- Риск случайного нажатия на отмену: снижается стилем `outlined` для `CANCELLED`.
- Риск расхождения логики переходов: отсутствует, т.к. используется единый источник `getAdminNextOrderStatuses`.
