KDS — Список заказов

Главный экран KDS-приложения. Live-обновляющийся список активных заказов выбранных станций, со звуковыми уведомлениями и цветовой индикацией времени.

Источник

BR 5.1 §1.1, §2 «Сценарии», §4 «Бизнес-правила» Бизнес-спека: Кухонный экран §2.3 «Видимость заказа», §2.6 «Цвет», §2.7 «Звук»


Что видит пользователь

Полноэкранное окно с list/grid карточек активных заказов. Сверху — мини-headers с названием выбранных станций и кнопкой «Меню». Карточки покрашены по времени до готовности (зелёный/жёлтый/красный). На новый заказ — звуковой сигнал.


Высокий 60px бар сверху:

ЭлементОписание
СлеваНазвание станций («🔥 Горячий цех» или «🔥 Кухня + 🍹 Бар» если multi-station). Шрифт жирный 22px
По центруЧасы (текущее время, обновляются каждую сек). Используются для расчёта цвета карточек
СправаКнопка-меню (⋮) — открывает Settings (см. Настройки)

Цвет фона header:

  • Тёмно-синий — обычное состояние
  • Красный — «Нет связи» (потеря WS/REST)
  • Жёлтый — «Есть несинхронизированные действия» (после reconnect)

Layout заказов

Опции

В Settings выбирается:

  1. Карточки сеткой (default) — grid-template-columns: repeat(auto-fill, minmax(280px, 1fr))
  2. Список — вертикальный одна карточка-строка на ширину экрана (для маленьких планшетов)

В обоих режимах — горизонтальный или вертикальный scroll по конфигу.

Сортировка

По created_at ASC (старые наверху). Это естественный FIFO.

В Settings (P1) — переключатель «Сначала срочные» (по expected_ready_at).


Карточка заказа в списке

┌────────────────────────────────────────┐
│ #001-234   🍽 Стол 5     ⏱ 14:35      │  ← order_number, type, expected_ready_at
│                                          │
│ • Карбонара (1) [preparing]             │  ← позиции выбранных станций
│ • Цезарь (1) [pending]                  │
│                                          │
│ + 1 поз. на других станциях             │  ← позиции ДРУГИХ станций (контекст)
│                                          │
│ комментарий: без лука                   │  ← если есть
└────────────────────────────────────────┘
   ↑ Цвет рамки/фона: зелёный/жёлтый/красный

Поля карточки

ПолеИсточникФормат
Номерorder.order_numberЖирный 18px, #001-234 (где 234 — order_number per-day)
Типorder.order_typeЭмоджи: 🍽 (dine_in + table_id) / 🛵 (delivery) / 🥡 (takeaway) + опц. подпись «Стол 5»
Время до готовностиorder.expected_ready_atФормат 14:35 или относительно: «через 4 мин», «просрочка 2 мин»
Позиции выбранных станцийorder.items[].kitchen_station_id IN selected_station_idsСписок с product_name (quantity) [kitchen_status]
Позиции других станцийте же items с другим kitchen_station_idСерый, агрегировано: «+ N поз. на других станциях»
Комментарийorder.commentЕсли есть, до 50 символов с

Цвет карточки

По правилу из бизнес-спеки §2.6:

const minutesLeft = (expected_ready_at - now) / 60;

// Берём минимум по выбранным станциям (самый "жёсткий" порог)
const yellow = min(selectedStations.map(s => s.yellow_threshold_minutes));  // default 5
const red = min(selectedStations.map(s => s.red_threshold_minutes));        // default 0

if (minutesLeft <= -red) return "red";       // просрочка
if (minutesLeft <= yellow) return "yellow";  // осталось мало
return "green";                              // в норме

Цвета (можно переопределить через Settings локально):

  • Зелёный — #1a8854 фон, белый текст
  • Жёлтый — #d99a00 фон, чёрный текст
  • Красный — #c93939 фон, белый текст; pulse-анимация (1 sec)

Пересчёт цвета — каждую секунду через React state-таймер.


Звуковое уведомление

Новый заказ

При получении WS-события order.created или order.cooking_started:

  1. Карточка появляется в списке с slide-in анимацией (300ms)
  2. Звук из kds_franchise_settings.new_order_sound (default bell.mp3)
  3. Звук повторяется каждые kds_franchise_settings.new_order_repeat_seconds (default 30s) пока повар не открыл карточку (тап на неё)

Просрочка

При переходе цвета yellow → red — однократно проигрывается kds_franchise_settings.overdue_sound (default alarm.mp3).

Громкость

kds_franchise_settings.sound_volume (0–100%). На устройстве можно локально переопределить.

Mute

В Settings — кнопка «🔕 Заглушить звук» (опционально, для краткосрочного периода — тише потом auto-restore через 10 мин).


Live-обновления

WebSocket

Каждый KDS держит одно WS-соединение wss://erp-test.nirbi.ru/api/v1/pos/kds/stream?station_ids=....

События:

EventДействие
order.createdДобавить карточку в список + звук
order.cooking_started (status accepted)То же что order.created если ещё не было в списке
order.item.kitchen_status_changedОбновить статус позиции; если все позиции ready — заказ уезжает с экрана с fade-out (300ms)
order.cancelledАлёрт «Заказ отменён» (звук + красное оверлей-уведомление 2-3 сек), потом fade-out
order.readyЗаказ уезжает с fade-out
device.revokedПринудительный logout + переход на экран регистрации
kds.settings.updated (P1)Re-pull настроек

Reconnect

  • Heartbeat ping каждые 25 сек
  • При потере соединения — баннер «Нет связи» в header (красный)
  • Авто-reconnect каждые 5 сек (exponential backoff до 30 сек)
  • При успешном reconnect → REST GET /orders?station_ids=...&status=active для синхронизации (если состояние разъехалось)

REST polling fallback

Если WS не открывается (firewall, прокси) — fallback на REST polling каждые 5 сек. Detected на стороне приложения по wsConnection.readyState !== OPEN через 10 сек после login.


Действия с карточкой

Тап на карточку

→ Открывается Карточка заказа (полный экран или модалка). Звук уведомления для этого заказа перестаёт повторяться.

Long-press

(Опционально, P1) — быстрое меню «Скрыть на 5 мин», «Передать другой станции».


Состояния пустого экрана

  • Заказов нет: фон тёмный, по центру: «🍴 Ожидание заказов» + название выбранных станций, время начала смены.
  • Загрузка: skeleton-карточки.
  • Ошибка загрузки: «Не удалось загрузить. Повторить» + кнопка.

Permissions

Доступ к экрану — только при kds.access. Без него экран не открывается (login-flow упирается в 403).


Off-screen behaviour

  • При уходе приложения в background — WS-соединение остаётся открытым
  • При возврате (resume) — приложение проверяет:
    • JWT не истёк → автообновление списка через REST + восстановление WS
    • JWT истёк → возврат на PIN-экран

Что НЕ входит в P0

  • Drag&drop позиций между станциями
  • Долгий тап → быстрое меню (P1)
  • Фильтр заказов по типу (зал/доставка/самовывоз) — BR 5.8
  • Курсы подачи (BR 5.6)
  • Анимированный pulse на карточке когда «давно не открывали»
  • Просмотр истории закрытых заказов

Связи