This commit is contained in:
Kirill
2026-05-28 21:20:35 +05:00
parent 966731d3e1
commit 7000fbffa7
10 changed files with 993 additions and 53 deletions
@@ -0,0 +1,114 @@
# Дизайн: Доработки админки заказов (маркер цены + быстрые статусы)
**Дата:** 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`.