Display de Cozinha (KDS)
Visão Geral
O KDS (Kitchen Display System) é a tela principal da cozinha. Pedidos entram em tempo real via WebSocket assim que o PDV ou o cliente confirma. A tela é full-screen, sempre dark, sem header de admin — pensada para tablets e monitores de cozinha.
| Característica | Detalhe |
|---|---|
| Rota | /t/:slug/kitchen |
| Auth | JWT obrigatório; roles aceitos: staff, branch_manager, admin, superadmin |
| WebSocket namespace | /kitchen |
| Frontend | frontend-react/src/views/kitchen/KitchenDisplayView.tsx |
| Backend | backend/src/kitchen/kitchen.gateway.ts |
Localização das Camadas
| Camada | Arquivo |
|---|---|
| WebSocket Gateway | backend/src/kitchen/kitchen.gateway.ts |
| SLA Processor | backend/src/kitchen/kitchen-sla.processor.ts |
| Order Card | frontend-react/src/components/kitchen/KitchenOrderCard.tsx |
| Recall Panel | frontend-react/src/components/kitchen/RecallPanel.tsx |
| KDS Keyboard Legend | frontend-react/src/components/kitchen/KdsKeyboardLegend.tsx |
Layout em Lanes
O display agrupa pedidos em quatro colunas (lanes):
| Lane | Status | Cor padrão |
|---|---|---|
| NOVO | pending | Laranja |
| CONFIRMADO | confirmed | Amarelo |
| PREPARANDO | preparing | Azul |
| PRONTO | ready | Verde |
A cor exata de cada lane vem de frontend-react/src/constants/statusColors.ts (KDS_LANE_COLORS).
Eventos WebSocket
Fluxo de entrada
OrdersService.create() → emitNewOrder(tenantId, order, zones[])
OrdersService.update() → emitOrderStatusUpdate(tenantId, order)
StoneService.webhook() → emitPaymentUpdate(tenantId, { orderId, paymentStatus })
KdsProcessor → emitOrderSlaAlert(tenantId, { orderId, elapsedMinutes, slaMinutes })Eventos emitidos pelo gateway
| Evento | Payload resumido | Destino |
|---|---|---|
newOrder | Pedido completo | Sala kitchen-{tenantId} |
newOrder (por zona) | Pedido filtrado por printZone | Sala kitchen-{tenantId}-{zone} |
orderStatusUpdate | Delta lean { _id, status, priority, updatedAt } | Sala kitchen-{tenantId} |
orderStatusUpdate | Pedido completo | Sala order-{orderNumber} (tracking do cliente) |
paymentUpdate | { orderId, paymentStatus, orderNumber } | Sala kitchen-{tenantId} |
itemStatusUpdate | { orderId, orderNumber, itemIndex, status } | Sala kitchen-{tenantId} |
orderSlaAlert | { orderId, orderNumber, elapsedMinutes, slaMinutes } | Sala kitchen-{tenantId} |
Eventos escutados pelo gateway (client → server)
| Evento | Payload | Ação |
|---|---|---|
joinKitchen | { tenantId, zone? } | Entra na sala. Superadmin pode entrar em qualquer tenant; auto-leave 30min |
trackOrder | orderNumber | Entra na sala order-{orderNumber} (com rate-limit 20/min) |
SLA — Tempo de Preparo Monitorado
A constante SLA_THRESHOLD_MINUTES = 12 (minutos) dispara destaque vermelho no card independente do SLA por pedido.
Cada Order pode ter slaMinutes customizado. O processador BullMQ kitchen-sla.processor.ts enfileira alertas quando o tempo decorrido ultrapassa o limiar:
emitOrderSlaAlert(tenantId, {
orderId,
orderNumber,
elapsedMinutes, // calculado em tempo real
slaMinutes, // vem de order.slaMinutes ?? branch.kdsSlaMinutes ?? 15
});O card reage ao evento orderSlaAlert: dispara playSlaBeep() (Web Audio API, sem arquivo externo) e exibe o card com borda vermelha pulsante.
Alertas de Alergia
Itens com restrição alimentar chegam no campo order.items[].notes ou em order.items[].allergens[]. O KitchenOrderCard exibe banner vermelho quando detecta a presença de:
allergens[]não vazio no itemnotescontendo termos como alergia, intolerância, sem glúten, sem lactose
Sinalizador impossível de ignorar — posição sempre acima da lista de itens, com ícone
AlertTriangle.
Roteamento por Zona (Print Zone)
O campo MenuItem.printZone determina para qual estação o item deve aparecer. Valores típicos:
| Zona | Estação |
|---|---|
hot | Cozinha quente |
cold | Cozinha fria / sobremesas |
bar | Bar / bebidas |
Quando a cozinha abre com ?zone=bar, o gateway entrega apenas os itens com printZone === 'bar' via emitNewOrder(tenantId, order, zones). Pedidos sem zona vão para o display sem filtro.
Configuração de zona por item: Admin → Cardápio → Item → Zona de Impressão.
Item-Level Status (por ingrediente/prato)
Além do status do pedido inteiro, cada item tem status próprio:
pending → in_preparation → ready → deliveredO atendente pode avançar item a item pelo KDS, permitindo que o garçom sirva itens prontos antes de toda a comanda estar completa. O backend emite itemStatusUpdate via WebSocket.
Bump Bar (Teclado)
O KDS suporta controle sem toque — útil quando o operador usa luvas:
| Tecla | Ação |
|---|---|
← / → | Mover foco entre pedidos |
↑ / ↓ | Rolar a lista |
Enter | Avançar status do pedido focado |
B | Avançar o primeiro item não-entregue (bump) |
R | Recall (desfaz bump) |
F | Marcar/desmarcar pedido como flagged |
O hook useKdsKeyboard (frontend-react/src/hooks/useKdsKeyboard.ts) gerencia o estado de foco e dispara onBump.
Recall Panel
Pedidos marcados como delivered (bump) aparecem no painel lateral de recall por 15 minutos. Um deslize para a esquerda (swipe ou botão R) restaura o pedido para ready. Útil quando o operador avança por engano.
Permissões
| Role | Acesso KDS |
|---|---|
customer | Bloqueado (WebSocket rejeita) |
staff | Leitura + atualização de status |
branch_manager | Leitura + atualização de status |
admin | Leitura + atualização de status |
superadmin | Qualquer tenant; auto-leave 30min |