Módulo 6 - Operações em Campo & Telemetria GPS (field-operations)
Módulo 6: Operações em Campo & Telemetria (field-operations)
Section titled “Módulo 6: Operações em Campo & Telemetria (field-operations)”O módulo Field Operations gerencia a atuação presencial da equipe nos imóveis dos clientes, capturando coordenadas GPS no check-in/out e calculando a compatibilidade entre a funcionária e a residência.
📍 1. Algoritmo de Matching de Equipe (StaffMatchingService)
Section titled “📍 1. Algoritmo de Matching de Equipe (StaffMatchingService)”Na hora de alocar uma funcionária para um cliente, o StaffMatchingService calcula um Score de Compatibilidade (0 a 100) considerando:
- Afinidade Prévia (40%): Histórico de limpezas bem-sucedidas no mesmo cliente.
- Proximidade Geográfica (40%): Distância em km entre a residência da funcionária e o imóvel.
- Preferência de Idioma (20%): Idioma de comunicação em comum entre a equipe e o cliente.
🛠️ 2. Arquivos Principais do Módulo
Section titled “🛠️ 2. Arquivos Principais do Módulo”- Matching de Equipe:
src/features/field-operations/services/StaffMatchingService.ts - Hook de Operações:
src/features/field-operations/hooks/useExecutionOperations.ts - Validação GPS & Ações de Campo:
src/components/service-detail/ServiceGeoAction.tsx- A checagem de proximidade de 20 segundos usa um gate por epoch de foreground/visita: serializa leituras normais, invalida resultados ao pausar/trocar/desmontar e solicita um fix novo na retomada. Uma posição tardia nunca dispara auto-start no atendimento anterior.
- Clock-in e finalização adquirem locks antes do primeiro
await; a preflight mostra busy e não fecha durante a captura. Toque duplo não duplica GPS, persistência ou Activity Log, e o preparo da evidência não conclui depois do teardown.
- Aviso de Deslocamento/Trânsito (Transporte Público):
src/components/service-detail/modals/TransitDelayModal.tsx&functions/api/channels/transitNotice.ts- O envio usa timeout de 15 segundos e controller pertencente ao pedido/cliente visível. Fechar, desmontar ou trocar esse owner aborta a operação; respostas antigas não produzem toast, háptico nem fechamento. Presets e ações ficam congelados durante o envio, e falha devolve a mesma superfície ao estado interativo para retry em desktop, PWA, Android e iOS.
- Upload de Fotos/Evidências:
src/components/service-detail/PhotoUploadZone.tsxenvia ao R2 comAbortSignal, epoch de sessão e confirmação autoritativa antes de anexar a URL ao pedido. - Custódia de Chaves:
KeyCustodyPanel.tsx+KeyCustodyApiService.tsusam/api/field/key-custody; inventário e histórico são persistidos em D1, com auditoria por trigger, autorização administrativa e controle de versão contra transferências concorrentes. Leituras/mutações possuem teto de 12/15 segundos, cancelamento e isolamento por identidade; troca de conta limpa os dados sensíveis e uma operação ativa desabilita todas as ações conflitantes. A interface usa os primitives oficiais, cards móveis/tabela desktop e exige seleção explícita do responsável antes da retirada. - Supply Hub: avisos de reposição são compostos sem alterar o cache compartilhado. Auditorias de IA possuem teto de 30 segundos, resposta validada e cancelamento; loading usa conjuntos por cliente, portanto análises/notificações paralelas permanecem visualmente corretas. Single-flight inclui a identidade na chave e epochs impedem resultado, toast ou loading tardio depois de logout/impersonação; insights são apagados imediatamente na troca de conta. Cópia usa o provider nativo/web e trata indisponibilidade do clipboard com feedback recuperável.
- Incidentes: formulário avulso e fechamento de turno usam
CFSelect,CFInput,IconBadgeeButton, com seleçõesaria-pressed, grids adaptativos e alvos de toque canônicos. A descrição é aparada antes do envio e um lock síncrono impede relatórios duplicados. A análise por IA mantém um únicoAbortController, é cancelada no teardown e mostra falha com opção real de retry.
Check-in, check-out e finalização calculam a próxima solicitação a partir do snapshot síncrono atual do store e publicam o estado otimista antes de rede, log ou toast. Nenhuma escrita ocorre dentro de um updater React/Zustand, portanto uma reinvocação do render não duplica D1 ou Activity Log. Eventos sequenciais no mesmo frame enxergam o resultado anterior, e uma tarefa removida antes da confirmação não produz falso sucesso de finalização em web, PWA, Android ou iOS.
Alocação individual/em série, conclusão manual e mudança administrativa de status seguem a mesma fronteira: o próximo estado é calculado fora do updater e cada tarefa aceita somente uma mutação em voo. Rejeição restaura o snapshot pertencente àquela tentativa; desmontagem ou troca de árvore invalida respostas, rollbacks e toasts tardios. Propagação recorrente e notificações verificam o lifecycle antes do feedback, evitando duplicação por toque/Strict Mode e conclusão vazando para outra sessão nas quatro plataformas.
🚇 3. Aviso de Deslocamento & Trânsito via Transporte Público (Londres TfL)
Section titled “🚇 3. Aviso de Deslocamento & Trânsito via Transporte Público (Londres TfL)”Quando a funcionária se desloca via metrô/ônibus e prevê uma variação no horário de início, o app calcula a estimativa de trânsito em tempo real (estimateLondonPublicTransit) e despacha com 1 clique uma notificação oficial assinada pela própria funcionária no canal da tarefa (JOB) e via WhatsApp para o cliente.
📶 4. Contrato de Conectividade para Fotos de Vistoria
Section titled “📶 4. Contrato de Conectividade para Fotos de Vistoria”Fotos não possuem fila offline: uma fila anterior guardava base64 em localStorage e conseguia enviar o arquivo depois, mas não reconciliava a URL resultante no pedido, criando risco de objeto órfão e falso sucesso. Agora a interface detecta ausência/falha de rede, informa que a foto precisa ser selecionada novamente e só chama onAdd depois da resposta válida do R2. O chat continua sendo a única funcionalidade com fila offline persistente, porque possui identidade, owner de sessão e reconciliação completas em IndexedDB.
O portal público /rate compartilha o transporte limitado das demais rotas públicas: contexto encerra em 12 segundos, envio em 15 segundos e teardown aborta a operação. Falha de rede mantém retry explícito e não vira falso “Service not found”; o lock síncrono preserva uma única avaliação em voo em web, PWA, Android e iOS.