
Денежное действие — последовательность состояний
Для betslip, placement и cashout нельзя ограничиваться enabled/disabled. Пользовательский путь проходит draft, local validation, server quote, confirm, pending, success или reject. Каждому состоянию нужен свой текст и допустимые действия; иначе интерфейс создаёт ложное ощущение финальности.
| Вопрос команды | Что фиксируем | Что считаем ошибкой |
|---|---|---|
| Что видит пользователь? | Явные состояния и переходы | Необъяснимый скачок или «вечный loading» |
| Кто источник истины? | Контракт клиента, API и внешнего источника | Два слоя считают себя финальными |
| Как деградируем? | Fallback, stale policy, retry и stop condition | Скрытый partial сбой |
Расчёт имеет срок жизни и подтверждение сервера
Цена, доступность рынка и лимиты меняются. Клиент может хранить draft, но финальная допустимость определяется сервером в момент quote/commit. UI обязан ясно показать reprice и дать пользователю осознанно подтвердить изменение, если продуктовая политика этого требует.
Приостановка — это не просто недоступная кнопка
Причина недоступности важна: рынок временно остановлен, событие завершено, данные устарели или аккаунт не может выполнить действие. От этого зависит сообщение, возможность retry и то, сохраняется ли selection в betslip.
Динамическая цена не должна ломать доступность
Рост/падение коэффициента можно показывать визуально, но значение, focus и accessible name не должны прыгать непредсказуемо. Live region применяется точечно; постоянные объявления каждого тика перегружают пользователя assistive technology.
Сценарий отказа проектируется вместе со штатным сценарием
Timeout не означает, что операция не произошла. После неопределённого ответа клиент должен сверить server state, а не предлагать повторить потенциально неидемпотентную команду. Для cashout и placement это ключевая граница между UX и транзакционной логикой.
Текст интерфейса — часть контракта состояния
Для betting UX формулировка ошибки влияет на следующее действие пользователя. «Ошибка» ничего не объясняет: рынок мог быть suspended, цена изменилась, лимит не прошёл или ответ сервера неизвестен из-за timeout. Эти ситуации должны иметь разные copy и разные разрешённые действия.
| Состояние | Что сообщаем | Допустимое действие |
|---|---|---|
| Repriced | Цена изменилась после draft | Показать новую цену и запросить осознанное подтверждение по правилам продукта |
| Suspended | Рынок временно недоступен | Сохранить контекст, но заблокировать commit |
| Rejected | Сервер отклонил команду с конкретной причиной | Исправить ввод или убрать selection |
| Unknown outcome | Клиент не знает финальный результат | Сверить server state; не повторять команду вслепую |
Такой copy-contract удобен и для accessibility testing: статус можно проверить независимо от цвета, а focus после перехода остаётся предсказуемым.
Проверка пользовательского опыта для критичных действий
Для каждого действия с финансовым результатом удобно проводить review по одной и той же последовательности: intent, validation, server quote, user confirmation, command, final reconciliation. Но визуальная композиция конкретного экрана может быть разной — важна полнота состояний, а не единый шаблон интерфейса.
- Пользователь понимает, изменилась ли цена после его последнего осознанного действия.
- Pending нельзя спутать с success.
- Timeout не превращается автоматически в «неудачу» и повторную отправку.
- Причина suspend не скрывается универсальным disabled-состоянием.
- Keyboard и assistive technology получают ту же семантику результата, что визуальный пользователь.
Финансовый сценарий лучше читать как диалог пользователя с системой
Кнопка «Поставить» — только один момент в цепочке. До неё пользователь собрал draft, после неё может получить reprice, ожидание, отказ или неизвестный результат. Хороший UX не пытается скрыть эти состояния, а объясняет каждое коротко и в тот момент, когда человек ещё может принять решение.
Поэтому copy проверяется вместе с контрактом. Если API возвращает один общий error, интерфейсу нечего объяснять. Если сервер различает suspended market, changed price и duplicate command, компонент может дать разные действия. Для практической проверки полезно открыть Betslip и LiveOddsTile.
Цена ошибки в букмекерском интерфейсе ощущается сразу
В betting-продукте интерфейс не имеет права «догадываться» о бизнес-статусе команды пользователя. Достаточно одного неочевидного reprice или невидимого suspend, чтобы доверие к экрану пропало. Поэтому в живом продукте сильнее всего работают не декоративные паттерны, а ясно прописанные состояния: выбранный исход, проверка цены, подтверждение, изменение условий и отказ. На уровне элемента это удобно смотреть через разбор кнопки коэффициента.
Второй болезненный участок — betslip. Пользователь думает, что взаимодействует с одной формой, а на самом деле проходит через локальный draft, серверную валидацию, quote и размещение команды. Если эти этапы не разведены, интерфейс начинает либо обещать лишнее, либо прятать реальную причину отказа. Поэтому для продуктовой команды полезно держать рядом и этот обзор, и статью про границу валидации betslip между UI и сервером.
Поддерживающие материалы
Ниже — подробные разборы отдельных решений: от состояния интерфейса и границ компонента до интеграции и поведения при отказе.