Modo Offline (PWA)
Visão Geral
O terminal PDV funciona como um Progressive Web App (PWA), permitindo operação contínua mesmo sem conexão com a internet. Pedidos realizados offline são armazenados localmente e sincronizados automaticamente ao reconectar.
Arquivos Principais
| Arquivo | Papel |
|---|---|
frontend-react/vite.config.ts | Configuração do plugin VitePWA com Workbox |
frontend-react/public/manifest.json | Manifesto PWA (nome, ícones, display standalone) |
frontend-react/src/services/offlineQueue.ts | Fila IndexedDB para pedidos pendentes |
frontend-react/src/hooks/useNetworkStatus.ts | Hook de detecção de conectividade |
frontend-react/src/views/pdv/PdvTerminalView.tsx | Banner offline + flush ao reconectar |
Estratégias de Cache (Workbox)
| Recurso | Estratégia | Descrição |
|---|---|---|
| Categorias e itens do cardápio | CacheFirst | Dados raramente mudam; servidos do cache |
| Configuração do tenant | CacheFirst | Logo, cores e dados do restaurante |
| Assets estáticos (JS/CSS/imagens) | CacheFirst | Nunca revalidados durante a sessão |
Pedidos (/t/*/orders) | NetworkFirst | Tenta a rede; se falhar, usa fila local |
Fila de Pedidos Offline
Localização: frontend-react/src/services/offlineQueue.ts
API Exportada
typescript
// Enfileira um pedido no IndexedDB (database: 'offline-queue', store: 'orders')
enqueueOrder(slug: string, payload: Record<string, unknown>): Promise<number>
// Processa todos os pedidos pendentes; retorna contagem de sucesso/falha
flushQueue(submitFn: (slug, payload) => Promise<unknown>): Promise<{ succeeded: number; failed: number }>
// Retorna quantidade de pedidos aguardando sync
countPendingOrders(): Promise<number>Estrutura do Registro
typescript
interface OfflineOrder {
id?: number; // auto-incremento IndexedDB
slug: string; // tenant slug
payload: object; // corpo do pedido (mesmo formato da API)
createdAt: string; // ISO timestamp do momento do registro
}Hook useNetworkStatus
Localização: frontend-react/src/hooks/useNetworkStatus.ts
typescript
const { isOnline, isFlushing } = useNetworkStatus();| Propriedade | Tipo | Descrição |
|---|---|---|
isOnline | boolean | true quando há conexão ativa |
isFlushing | boolean | true enquanto está sincronizando a fila |
O hook escuta os eventos window.online / window.offline e chama flushQueue() automaticamente ao reconectar.
Banner Offline no Terminal
Quando isOnline === false, o PdvTerminalView exibe um banner no topo da tela:
⚠ Modo offline — pedidos serão sincronizados ao reconectar (X pendentes)Quando isFlushing === true (ao reconectar):
↑ Sincronizando X pedido(s) offline...Instalação como App
O PWA pode ser instalado no dispositivo via browser:
- Chrome/Edge: Ícone de instalação na barra de endereços
- iOS Safari: Compartilhar → Adicionar à Tela de Início
- Android Chrome: Menu → Instalar app
Após instalado, o terminal abre em modo standalone (sem barra do browser).
Limitações do Modo Offline
- Cardápio e preços servidos do cache — alterações feitas durante a queda só aparecem após reconexão
- Impressão fiscal (NF-e) requer conexão (Focus NFe é externo)
- PIX QR Code requer conexão para gerar (dados do tenant precisam estar cacheados)
- Máximo prático: ~500 pedidos em fila (limite da IndexedDB por quotas do browser)