Integração Frontend: API & Performance
Integração Frontend: API & Performance
NexarGrid Documentation • v beta-2.0.1
Este documento descreve como a aplicação frontend se comunica com os microsserviços backend e as estratégias empregadas para garantir uma experiência de usuário responsiva.
# Padrões de Integração de API
Utilizamos o Repository Pattern para abstrair chamadas de API dos componentes de UI. Isso permite testes e mocking mais fáceis.
# Camada de Serviço (src/services/)
Cada domínio do backend possui um arquivo de serviço correspondente:
AuthService.ts: Login, refresh token, redefinição de senha.GridService.ts: Busca de dados do grid, salvamento de alterações.RosteredService.ts: Gerenciamento de perfis profissionais.
Exemplo: GridService.ts
import api from '@/boot/axios';
import { ShiftPack } from '@/types';
export default {
async getByUnitAndMonth(unitId: string, month: string): Promise<ShiftPack[]> {
const response = await api.get(`/api/shiftPack/list`, {
params: { unitId, month }
});
return response.data;
},
async createShift(payload: CreateShiftPayload): Promise<ShiftItem> {
const response = await api.post('/api/shiftItem/create', payload);
return response.data;
},
async formatBulkSlots(payload: BulkSlotPayload): Promise<ApiResponse> {
// Usado para criação de turnos customizados (repetidor)
// payload.purgeBeforeInsert = true garante atomicidade
const response = await api.post('/api/shiftPack/formatBulkSlots', payload);
return response.data;
}
};
# Persistência de Turnos Customizados (applyCustomShiftItems)
Quando usuários definem turnos customizados via SlotSchedullerContainer, o frontend deve garantir que essas alterações sejam aplicadas atomicamente. Usamos o endpoint formatBulkSlots com a flag purgeBeforeInsert.
Action da Store (gridStore.js):
async applyCustomShiftItems({ slotId, shiftPackId, customTurnos }) {
// 1. Transforma objetos da UI em Modelos de Domínio
const newShiftItems = customTurnos.map((turno, index) => {
const duration = calculateDurationMinutes(turno.startTime, turno.endTime);
return new ShiftItemModel({
startTime: turno.startTime,
endTime: turno.endTime,
duration: duration,
position: index,
isShort: duration <= 60, // Calculado para UI, não persistido
// ...
});
});
// 2. Constrói o Payload
const payload = {
items: [{ shiftPackId, slotId, shiftItems: newShiftItems }],
purgeBeforeInsert: true // CRÍTICO: Remove itens antigos antes de inserir novos
};
// 3. Envia para o BFF
await SurrealService.formatBulkSlots(payload);
// 4. Recarrega o Grid para sincronizar estado
await this.loadShiftPacks(this.selectedGrid.id);
}
# Tratamento Global de Erros
Um interceptador Axios captura todos os erros de API e os despacha para o sistema de notificação:
- 401 Unauthorized: Redireciona para login (ou tenta refresh).
- 403 Forbidden: Mostra toast de “Acesso Negado”.
- 422 Validation Error: Destaca campos do formulário com mensagens do servidor.
- 500 Server Error: Mostra uma mensagem genérica de “Erro no Sistema” e loga o trace ID.
# Atualizações em Tempo Real (WebSockets)
Para suportar edição colaborativa, o frontend mantém uma conexão WebSocket (via cliente Socket.io) com o backend.
- Evento:
grid.updated - Payload:
{ unitId, month, modifiedBy } - Ação: Se o usuário estiver visualizando o grid afetado, um toast “Novos dados disponíveis” aparece, ou o grid se auto-atualiza (configurável).
# Otimização de Performance
# 1. Atualizações de UI Otimistas
Quando um usuário move um turno, a UI atualiza imediatamente, antes que a resposta da API seja recebida.
- Sucesso: O spinner de carregamento desaparece.
- Falha: O turno volta para sua posição original, e um toast de erro é mostrado.
# 2. Cache e Enriquecimento de Dados
Implementamos uma estratégia de cache para minimizar requisições de rede e enriquecer dados brutos com propriedades específicas de UI.
- Stale-While-Revalidate: Dados de grid em cache são mostrados instantaneamente enquanto uma busca em segundo plano verifica atualizações.
- Enriquecimento de Dados: Como o backend não armazena flags específicas de UI (como
isShort), estas são calculadas em tempo de execução durante o processo de carregamento de dados.
// gridStore.js
_enrichShiftPacks(shiftPacks) {
return shiftPacks.map(shiftPack => ({
...shiftPack,
shiftItems: (shiftPack.shiftItems || []).map(shiftItem => ({
...shiftItem,
// Recalcula flags de UI que não são persistidas
isShort: shiftItem.duration <= 60
}))
}));
}
# 3. Otimização de Bundle
- Tree Shaking: Componentes Quasar não utilizados são excluídos do build.
- Gzip/Brotli: Assets são comprimidos durante o processo de build.
- Otimização de Imagem: Avatares de usuários e assets estáticos são servidos via CDN com capacidades de redimensionamento.
# Estratégia de Testes
- Testes Unitários (Vitest): Foco em funções utilitárias, lógica de store e propriedades computadas complexas.
- Testes de Componente (Vue Test Utils): Verificam se componentes renderizam corretamente e emitem os eventos esperados.
- Testes E2E (Cypress): Simulam fluxos críticos do usuário: Login -> Abrir Grid -> Criar Turno -> Publicar.