Skip to content

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

ArquivoPapel
frontend-react/vite.config.tsConfiguração do plugin VitePWA com Workbox
frontend-react/public/manifest.jsonManifesto PWA (nome, ícones, display standalone)
frontend-react/src/services/offlineQueue.tsFila IndexedDB para pedidos pendentes
frontend-react/src/hooks/useNetworkStatus.tsHook de detecção de conectividade
frontend-react/src/views/pdv/PdvTerminalView.tsxBanner offline + flush ao reconectar

Estratégias de Cache (Workbox)

RecursoEstratégiaDescrição
Categorias e itens do cardápioCacheFirstDados raramente mudam; servidos do cache
Configuração do tenantCacheFirstLogo, cores e dados do restaurante
Assets estáticos (JS/CSS/imagens)CacheFirstNunca revalidados durante a sessão
Pedidos (/t/*/orders)NetworkFirstTenta 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();
PropriedadeTipoDescrição
isOnlinebooleantrue quando há conexão ativa
isFlushingbooleantrue enquanto está sincronizando a fila

O hook escuta os eventos window.online / window.offline e chama flushQueue() automaticamente ao reconectar.

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)

Relacionados

Lançado sob a licença MIT.