1049 lines
30 KiB
Markdown
1049 lines
30 KiB
Markdown
# Model Context Protocol (MCP) - Angular Workspace
|
|
|
|
## 📋 Visão Geral do Projeto
|
|
|
|
Este é um workspace Angular multi-projeto com foco em gerenciamento de frota de veículos (PraFrota), incluindo sistema de escala e aplicações IDT. O projeto utiliza Angular 19.2.x com arquitetura modular baseada em domínios.
|
|
|
|
## 🏗️ Estrutura do Workspace
|
|
|
|
```
|
|
angular-workspace/
|
|
├── projects/
|
|
│ ├── idt_app/ # Aplicação principal PraFrota
|
|
│ ├── idt_pattern/ # Biblioteca de padrões
|
|
│ ├── libs/ # Bibliotecas compartilhadas
|
|
│ ├── cliente/ # Aplicação cliente
|
|
│ └── escala/ # Sistema de escala
|
|
├── environments/ # Configurações de ambiente
|
|
├── proxy.conf.json # Configuração de proxy
|
|
└── mercado-live-routes-data.json # Dados de rotas
|
|
```
|
|
|
|
### Projetos Principais
|
|
|
|
1. **idt_app**: Aplicação principal para gerenciamento de frota
|
|
2. **escala**: Sistema de gerenciamento de escalas
|
|
3. **cliente**: Aplicação voltada para clientes
|
|
4. **libs**: Bibliotecas compartilhadas entre projetos
|
|
|
|
## 📊 Dashboard Tab System ⭐ **NOVO**
|
|
|
|
### Visão Geral
|
|
Sistema de dashboard automático integrado ao `BaseDomainComponent` que adiciona uma aba de dashboard antes da aba de lista em qualquer domínio.
|
|
|
|
### Características
|
|
- **Aba Dashboard**: Aparece automaticamente ANTES da "Lista de [Domínio]"
|
|
- **KPIs Automáticos**: Total, Ativos, Recentes (últimos 7 dias)
|
|
- **KPIs Customizados**: Definidos por domínio
|
|
- **Design Responsivo**: Desktop e mobile
|
|
- **Dark Mode**: Suporte completo
|
|
- **Configuração Simples**: Apenas uma flag `showDashboardTab: true`
|
|
|
|
### Implementação
|
|
```typescript
|
|
// Em qualquer domínio (ex: vehicles.component.ts)
|
|
protected override getDomainConfig(): DomainConfig {
|
|
return {
|
|
domain: 'vehicle',
|
|
title: 'Veículos',
|
|
entityName: 'veículo',
|
|
subTabs: ['dados', 'documentos'],
|
|
showDashboardTab: true, // ✅ Habilita dashboard
|
|
dashboardConfig: { // ✅ Configuração opcional
|
|
customKPIs: [
|
|
{
|
|
id: 'active-vehicles',
|
|
label: 'Veículos Ativos',
|
|
value: '150',
|
|
icon: 'fas fa-car',
|
|
color: 'success',
|
|
trend: 'up',
|
|
change: '+5%'
|
|
}
|
|
]
|
|
},
|
|
columns: [...]
|
|
};
|
|
}
|
|
```
|
|
|
|
### Componentes Envolvidos
|
|
- `BaseDomainComponent`: Lógica de criação das abas
|
|
- `DomainDashboardComponent`: Componente visual do dashboard
|
|
- `TabSystemComponent`: Renderização das abas
|
|
|
|
### Documentação
|
|
- [Dashboard Tab System Guide](../components/DASHBOARD_TAB_SYSTEM.md)
|
|
- [BaseDomainComponent](../architecture/BASE_DOMAIN_COMPONENT.md)
|
|
|
|
## 🎯 Domínios de Negócio
|
|
|
|
### IDT App - Estrutura de Domínios
|
|
|
|
```
|
|
projects/idt_app/src/app/domain/
|
|
├── vehicles/ # Gerenciamento de veículos
|
|
├── drivers/ # Gerenciamento de motoristas
|
|
├── routes/ # Gerenciamento de rotas
|
|
├── finances/ # Gestão financeira
|
|
└── session/ # Controle de sessão
|
|
```
|
|
|
|
### Shared Resources
|
|
|
|
```
|
|
projects/idt_app/src/app/shared/
|
|
├── components/ # Componentes reutilizáveis
|
|
│ └── tab-system/ # Sistema de abas para edição
|
|
├── services/ # Serviços compartilhados
|
|
└── interfaces/ # Interfaces TypeScript
|
|
```
|
|
|
|
## 🔧 Configurações Técnicas
|
|
|
|
### Scripts NPM Principais
|
|
|
|
- `ng serve`: Desenvolvimento geral
|
|
- `ESCALA_development`: Desenvolvimento do sistema de escala
|
|
- `serve:prafrota`: Desenvolvimento da aplicação PraFrota
|
|
- `build:prafrota`: Build de produção da aplicação PraFrota
|
|
- `build:prafrota --watch`: Build contínuo para desenvolvimento PWA
|
|
- `http-server dist/idt_app -p 8080 --ssl`: Servir PWA com HTTPS local
|
|
|
|
### Dependências Principais
|
|
|
|
- **Angular**: 19.2.13 (Core framework)
|
|
- **Angular Material**: 19.2.9 (UI Components)
|
|
- **Leaflet**: Mapas interativos
|
|
- **NgxMask**: Máscaras de input
|
|
- **RxJS**: Programação reativa
|
|
- **TypeScript**: 5.5.4
|
|
|
|
## 🌐 Integração de APIs
|
|
|
|
### Backend Principal - PraFrota
|
|
- **URL Base**: `https://prafrota-be-bff-tenant-api.grupopra.tech`
|
|
- **Versão**: v1
|
|
- **Autenticação**: Bearer Token (JWT)
|
|
|
|
### APIs Externas Integradas
|
|
|
|
#### ViaCEP (Consulta CEP)
|
|
- **URL**: `https://viacep.com.br/ws/{CEP}/json/`
|
|
- **Proxy**: Configurado via `proxy.conf.json`
|
|
- **Service**: `CepService`
|
|
|
|
#### Mercado Livre Routes
|
|
- **Endpoints**: Multiple APIs consolidados
|
|
- **Paginação**: Client-side para múltiplas APIs
|
|
- **Tipos**: FirstMile, LineHaul, LastMile
|
|
|
|
## 📊 Padrões de Dados
|
|
|
|
### Interfaces de Rotas Mercado Livre
|
|
|
|
```typescript
|
|
// Union type para diferentes tipos de rota
|
|
type MercadoLiveRouteRaw = FirstMileRoute | LineHaulRoute | LastMileRoute;
|
|
|
|
// Interface unificada para exibição
|
|
interface MercadoLiveRoute {
|
|
id: string;
|
|
routeType: 'first_mile' | 'line_haul' | 'last_mile';
|
|
vehicleType?: string;
|
|
locationName?: string;
|
|
driverName?: string;
|
|
departureDate?: Date;
|
|
status: string;
|
|
// ... outros campos unificados
|
|
}
|
|
```
|
|
|
|
### Mapeamento de Dados
|
|
|
|
Padrão de mapeamento type-safe para consolidação de APIs:
|
|
|
|
```typescript
|
|
class RouteMapper {
|
|
static mapRoutesToInterface(routes: MercadoLiveRouteRaw[]): MercadoLiveRoute[]
|
|
static mapFirstMileRoute(route: FirstMileRoute): MercadoLiveRoute
|
|
static mapLineHaulRoute(route: LineHaulRoute): MercadoLiveRoute
|
|
static mapLastMileRoute(route: LastMileRoute): MercadoLiveRoute
|
|
}
|
|
```
|
|
|
|
## 🔍 Serviços Principais
|
|
|
|
### Logger Service
|
|
Sistema de logging estruturado com buffer e formatação:
|
|
|
|
```typescript
|
|
interface LoggerService {
|
|
debug(message: string, ...args: any[]): void;
|
|
info(message: string, ...args: any[]): void;
|
|
warn(message: string, ...args: any[]): void;
|
|
error(message: string, ...args: any[]): void;
|
|
}
|
|
```
|
|
|
|
### CEP Service
|
|
Consulta de endereços via ViaCEP:
|
|
|
|
```typescript
|
|
@Injectable()
|
|
export class CepService {
|
|
consultarCep(cep: string): Observable<CepResponse>
|
|
}
|
|
```
|
|
|
|
### Route Services
|
|
Gerenciamento de rotas com paginação local:
|
|
|
|
```typescript
|
|
@Injectable()
|
|
export class MercadoLiveService {
|
|
loadRoutes(page: number, pageSize: number): Observable<PaginatedResponse>
|
|
}
|
|
```
|
|
|
|
## 🎨 Padrões de Componentes
|
|
|
|
### Standalone Components
|
|
Todos os componentes utilizam o padrão standalone:
|
|
|
|
```typescript
|
|
@Component({
|
|
selector: 'app-component',
|
|
standalone: true,
|
|
imports: [CommonModule, ReactiveFormsModule, MaterialModules],
|
|
templateUrl: './component.html'
|
|
})
|
|
```
|
|
|
|
### 🎯 TEMPLATE HTML OBRIGATÓRIO - BaseDomainComponent
|
|
|
|
TODOS os componentes que estendem BaseDomainComponent DEVEM usar exatamente este template HTML:
|
|
|
|
```html
|
|
<div class="domain-container">
|
|
<div class="main-content">
|
|
<app-tab-system
|
|
#tabSystem
|
|
[config]="tabConfig"
|
|
[events]="tabEvents"
|
|
[showDebugInfo]="false"
|
|
(tabSelected)="onTabSelected($event)"
|
|
(tabClosed)="onTabClosed($event)"
|
|
(tabAdded)="onTabAdded($event)"
|
|
(tableEvent)="onTableEvent($event)">
|
|
</app-tab-system>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
**Componentes que seguem este padrão:**
|
|
- VehiclesComponent ✅
|
|
- DriversComponent ✅
|
|
- RoutesComponent ✅
|
|
- FinancialCategoriesComponent ✅
|
|
- AccountPayableComponent ✅
|
|
|
|
### 🎯 PADRÃO OBRIGATÓRIO - Services com ApiClientService
|
|
|
|
**NUNCA usar HttpClient diretamente!** Todos os services DEVEM usar ApiClientService:
|
|
|
|
```typescript
|
|
import { Injectable } from '@angular/core';
|
|
import { Observable, map } from 'rxjs';
|
|
import { ApiClientService } from '../../shared/services/api/api-client.service';
|
|
import { DomainService } from '../../shared/components/base-domain/base-domain.component';
|
|
|
|
@Injectable({
|
|
providedIn: 'root'
|
|
})
|
|
export class ExampleService implements DomainService<Entity> {
|
|
|
|
constructor(
|
|
private apiClient: ApiClientService // ✅ CORRETO
|
|
// private http: HttpClient // ❌ ERRADO
|
|
) {}
|
|
|
|
getEntities(page: number, pageSize: number, filters: any): Observable<any> {
|
|
return this.apiClient.get<any>(`entities?page=${page}&limit=${pageSize}`);
|
|
}
|
|
|
|
create(data: any): Observable<Entity> {
|
|
return this.apiClient.post<Entity>('entities', data);
|
|
}
|
|
|
|
update(id: any, data: any): Observable<Entity> {
|
|
return this.apiClient.patch<Entity>(`entities/${id}`, data);
|
|
}
|
|
|
|
getById(id: string): Observable<Entity> {
|
|
return this.apiClient.get<Entity>(`entities/${id}`);
|
|
}
|
|
|
|
delete(id: string): Observable<void> {
|
|
return this.apiClient.delete<void>(`entities/${id}`);
|
|
}
|
|
}
|
|
```
|
|
|
|
**Services que seguem este padrão:**
|
|
- VehiclesService ✅
|
|
- DriversService ✅
|
|
- RoutesService ✅
|
|
- FinancialCategoriesService ✅
|
|
- AccountPayableService ✅
|
|
|
|
### 🚫 PADRÕES DE NOMENCLATURA OBRIGATÓRIOS
|
|
|
|
**NUNCA criar métodos com sufixos específicos!** Todos os services DEVEM seguir a nomenclatura padrão:
|
|
|
|
#### ✅ MÉTODOS CORRETOS:
|
|
```typescript
|
|
// Métodos da interface DomainService (OBRIGATÓRIOS)
|
|
getEntities(page: number, pageSize: number, filters: any)
|
|
create(data: any): Observable<Entity>
|
|
update(id: any, data: any): Observable<Entity>
|
|
|
|
// Métodos específicos padrão (OBRIGATÓRIOS)
|
|
getById(id: string): Observable<Entity>
|
|
delete(id: string): Observable<void>
|
|
get[Domain]s(page, limit, filters): Observable<PaginatedResponse<Entity>>
|
|
```
|
|
|
|
#### ❌ MÉTODOS INCORRETOS (NUNCA usar):
|
|
```typescript
|
|
// ❌ ERRADO - Com sufixos específicos
|
|
createRoute() // Usar apenas: create()
|
|
updateRoute() // Usar apenas: update()
|
|
deleteRoute() // Usar apenas: delete()
|
|
getRoute() // Usar apenas: getById()
|
|
|
|
// ❌ ERRADO - Nomenclatura não padronizada
|
|
addEntity(), editEntity(), removeEntity(), findById()
|
|
```
|
|
|
|
#### 📋 VERIFICAÇÃO DE CONFORMIDADE:
|
|
| Service | create | update | delete | getById | get[Domain]s |
|
|
|---------|--------|--------|--------|---------|--------------|
|
|
| VehiclesService | ✅ | ✅ | ✅ | ✅ | getVehicles ✅ |
|
|
| DriversService | ✅ | ✅ | ✅ | ✅ | getDrivers ✅ |
|
|
| RoutesService | ✅ | ✅ | ✅ | ✅ | getRoutes ✅ |
|
|
| FinancialCategoriesService | ✅ | ✅ | ✅ | ✅ | getCategories ✅ |
|
|
| AccountPayableService | ✅ | ✅ | ✅ | ✅ | getAccounts ✅ |
|
|
|
|
### Reactive Forms
|
|
Formulários construídos com FormBuilder:
|
|
|
|
```typescript
|
|
constructor(private fb: FormBuilder) {
|
|
this.form = this.fb.group({
|
|
field: ['', [Validators.required]]
|
|
});
|
|
}
|
|
```
|
|
|
|
### Data Tables
|
|
Componentes de tabela com paginação, filtros e ordenação usando Angular Material.
|
|
|
|
### Tab System - Sistema de Abas para Edição
|
|
Sistema avançado de abas para edição de registros com limite configurável e gestão de estado:
|
|
|
|
#### Configuração Básica
|
|
```typescript
|
|
// Configuração do sistema de abas
|
|
const tabConfig: TabSystemConfig = {
|
|
maxTabs: 3, // Limite máximo de abas
|
|
allowDuplicates: false, // Previne duplicatas
|
|
autoSave: false, // Auto-save desabilitado
|
|
confirmClose: true // Confirmação para fechar
|
|
};
|
|
|
|
// Eventos do sistema
|
|
const tabEvents = {
|
|
onMaxTabsReached: () => {
|
|
console.warn('Limite máximo de abas atingido!');
|
|
},
|
|
onUnsavedChanges: (tabs: TabItem[]) => {
|
|
console.warn('Mudanças não salvas:', tabs);
|
|
}
|
|
};
|
|
```
|
|
|
|
#### Uso no Template
|
|
```html
|
|
<app-tab-system
|
|
[config]="tabConfig"
|
|
[events]="tabEvents"
|
|
[showDebugInfo]="true"
|
|
(tabSelected)="onTabSelected($event)"
|
|
(tabClosed)="onTabClosed($event)"
|
|
(tabAdded)="onTabAdded($event)">
|
|
</app-tab-system>
|
|
```
|
|
|
|
#### Adicionar Aba Programaticamente
|
|
```typescript
|
|
async addNewTab(item: any) {
|
|
const tabItem: TabItem = {
|
|
id: item.id,
|
|
title: item.name,
|
|
type: 'driver', // 'product' | 'vehicle' | 'driver' | 'route'
|
|
data: item,
|
|
isLoading: true,
|
|
isModified: false
|
|
};
|
|
|
|
const success = await this.tabSystem.addTab(tabItem);
|
|
if (success) {
|
|
// Carregar dados detalhados
|
|
this.loadItemDetails(item.id);
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Aplicação no Domínio de Motoristas
|
|
Exemplo prático implementado em `drivers-tabs-demo.component.ts`:
|
|
|
|
```typescript
|
|
@Component({
|
|
selector: 'app-drivers-tabs-demo',
|
|
standalone: true,
|
|
imports: [/* Material modules */, TabSystemComponent]
|
|
})
|
|
export class DriversTabsDemoComponent {
|
|
@ViewChild('tabSystem') tabSystem!: TabSystemComponent;
|
|
|
|
// Configuração específica para motoristas
|
|
tabConfig: TabSystemConfig = {
|
|
maxTabs: 4,
|
|
allowDuplicates: false,
|
|
autoSave: false,
|
|
confirmClose: true
|
|
};
|
|
|
|
async addDriverTab(driver: Driver): Promise<void> {
|
|
const tabItem: TabItem = {
|
|
id: driver.id,
|
|
title: driver.name,
|
|
type: 'driver',
|
|
data: driver,
|
|
isLoading: true,
|
|
isModified: false
|
|
};
|
|
|
|
const success = await this.tabSystem.addTab(tabItem);
|
|
|
|
if (success) {
|
|
// Simular carregamento de detalhes
|
|
setTimeout(() => {
|
|
this.loadDriverDetails(driver.id);
|
|
}, 1500);
|
|
}
|
|
}
|
|
|
|
private loadDriverDetails(driverId: string): void {
|
|
// Encontrar a aba e atualizar com dados detalhados
|
|
const tabs = this.tabSystem.getTabs();
|
|
const tabIndex = tabs.findIndex(tab =>
|
|
tab.id === driverId && tab.type === 'driver'
|
|
);
|
|
|
|
if (tabIndex !== -1) {
|
|
const detailedData = {
|
|
documents: { cnh: '123456789', cnh_expiry: new Date() },
|
|
performance_score: 85,
|
|
status: 'ATIVO'
|
|
};
|
|
|
|
this.tabSystem.tabSystemService.updateTab(tabIndex, detailedData);
|
|
this.tabSystem.tabSystemService.setTabLoading(tabIndex, false);
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Funcionalidades do Sistema de Abas
|
|
- **Limite Configurável**: Máximo de abas simultâneas
|
|
- **Prevenção de Duplicatas**: Não permite abrir o mesmo item duas vezes
|
|
- **Estados de Loading**: Indicadores visuais durante carregamento
|
|
- **Indicadores de Modificação**: Marcação (*) para itens não salvos
|
|
- **Ícones por Tipo**: product, vehicle, driver, route
|
|
- **Botões de Fechar**: Com tooltips e confirmação
|
|
- **Responsividade**: Adaptação para dispositivos móveis
|
|
- **Otimização Mobile**: Títulos compactos para telas ≤ 768px
|
|
- **Debug Mode**: Informações de desenvolvimento
|
|
- **Eventos**: Sistema completo de callbacks
|
|
|
|
#### Otimização Mobile dos Títulos das Tabs
|
|
Sistema automático de formatação de títulos para dispositivos móveis:
|
|
|
|
```typescript
|
|
// Comportamento automático baseado no tamanho da tela
|
|
// Mobile (≤ 768px):
|
|
"Motorista: João Silva" → "João Silva"
|
|
"Veículo: Toyota Corolla" → "Toyota Corolla"
|
|
"Novo Motorista" → "Novo Motorista" (inalterado)
|
|
|
|
// Desktop (> 768px):
|
|
"Motorista: João Silva" → "Motorista: João Silva" (completo)
|
|
```
|
|
|
|
**Implementação:**
|
|
- **Detecção**: Automática via `@HostListener('window:resize')`
|
|
- **Lógica**: Remove domínio apenas se contém ":" e não inicia com "Novo"
|
|
- **Responsivo**: Atualização instantânea ao redimensionar
|
|
- **Universal**: Funciona para todos os domínios (motoristas, veículos, etc.)
|
|
|
|
## 📊 Data-Table - Otimização Mobile
|
|
|
|
### Melhorias de Responsividade
|
|
|
|
#### Header da Tabela (Mobile ≤ 768px)
|
|
**Layout reorganizado em duas linhas:**
|
|
|
|
```
|
|
┌─────────────────────────────────────┐
|
|
│ [🔍 Busca Global - 80%] [Filtros-20%]│ ← Linha 1
|
|
│ [Requisições] [Col] [Grup] [5▼] [Exp] │ ← Linha 2
|
|
└─────────────────────────────────────┘
|
|
```
|
|
|
|
**Funcionalidades:**
|
|
- **Busca Global**: 80% da largura para máximo aproveitamento
|
|
- **Botões Compactos**: Textos reduzidos ("Col", "Grup", "Exp")
|
|
- **Layout Edge-to-Edge**: Sem bordas laterais para ganho de espaço
|
|
- **Filtros Expansíveis**: Sistema toggle para filtros por coluna
|
|
|
|
#### Paginação Otimizada
|
|
|
|
**Mobile:**
|
|
```
|
|
┌─────────────────────────────────────┐
|
|
│ 1-5 de 5 [◀] [1] [2] [3] [▶] │ ← Linha única
|
|
└─────────────────────────────────────┘
|
|
```
|
|
|
|
**Melhorias implementadas:**
|
|
- **Texto Compacto**: "1-5 de 5" ao invés de "Exibindo 1 a 5 de 5 registros"
|
|
- **Altura Reduzida**: padding otimizado (0.375rem mobile vs 0.75rem desktop)
|
|
- **Layout Horizontal**: Forçado em linha única para mobile
|
|
- **Alinhamento Inteligente**: Texto à esquerda, controles à direita
|
|
- **Navegação Compacta**: Botões menores com espaçamento otimizado
|
|
|
|
#### CSS Budget Management
|
|
Sistema de compressão avançada para manter funcionalidades dentro do limite:
|
|
|
|
```scss
|
|
// Seção ultra-comprimida para mobile
|
|
@media (max-width: 768px) {
|
|
.data-table-container,.table-menu{border-left:none!important;border-right:none!important;border-radius:0!important;margin:0!important}
|
|
.pagination{padding:.375rem .5rem!important;flex-direction:row!important;justify-content:space-between!important}
|
|
// ... regras comprimidas
|
|
}
|
|
```
|
|
|
|
**Estratégias aplicadas:**
|
|
- **Compressão Manual**: Remoção de espaços e comentários
|
|
- **Seletores Combinados**: Agrupamento de regras similares
|
|
- **Important Flags**: Uso estratégico para sobrescrever padrões
|
|
- **Propriedades Mínimas**: Apenas essenciais para mobile
|
|
|
|
## 📄 Paginação Multi-API
|
|
|
|
### Padrão para Consolidação de APIs
|
|
|
|
```typescript
|
|
loadRoutes(page: number, pageSize: number) {
|
|
// 1. Buscar dados de múltiplas APIs
|
|
const requests = [
|
|
this.api.getFirstMile(1, 1000),
|
|
this.api.getLineHaul(1, 1000),
|
|
this.api.getLastMile(1, 1000)
|
|
];
|
|
|
|
// 2. Consolidar dados
|
|
forkJoin(requests).subscribe(results => {
|
|
const allRoutes = results.flat();
|
|
const mappedRoutes = this.mapRoutesToInterface(allRoutes);
|
|
|
|
// 3. Aplicar paginação local
|
|
const startIndex = (page - 1) * pageSize;
|
|
const endIndex = startIndex + pageSize;
|
|
const paginatedRoutes = mappedRoutes.slice(startIndex, endIndex);
|
|
|
|
this.routes = paginatedRoutes;
|
|
this.totalCount = mappedRoutes.length;
|
|
});
|
|
}
|
|
```
|
|
|
|
## 🗂️ Estrutura de Arquivos
|
|
|
|
### Convenções de Nomenclatura
|
|
|
|
- **Arquivos**: `kebab-case` (ex: `vehicle-form.component.ts`)
|
|
- **Classes**: `PascalCase` (ex: `VehicleFormComponent`)
|
|
- **Propriedades**: `camelCase` (ex: `vehicleName`)
|
|
- **Constantes**: `SCREAMING_SNAKE_CASE` (ex: `API_BASE_URL`)
|
|
|
|
### Organização por Feature
|
|
|
|
```
|
|
domain/vehicles/
|
|
├── components/
|
|
│ ├── vehicle-form/
|
|
│ ├── vehicle-list/
|
|
│ └── vehicle-map/
|
|
├── services/
|
|
│ └── vehicle.service.ts
|
|
├── interfaces/
|
|
│ └── vehicle.interface.ts
|
|
└── vehicle.routes.ts
|
|
```
|
|
|
|
## ⚙️ Configurações de Desenvolvimento
|
|
|
|
### Proxy Configuration
|
|
```json
|
|
{
|
|
"/api/ws/*": {
|
|
"target": "https://viacep.com.br",
|
|
"secure": true,
|
|
"changeOrigin": true,
|
|
"logLevel": "debug"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Environment Configuration
|
|
- **Development**: Local development settings
|
|
- **Production**: Production optimizations
|
|
- **Debug Remote**: Remote debugging configuration
|
|
|
|
## 🔐 Autenticação e Segurança
|
|
|
|
### Headers Obrigatórios
|
|
```http
|
|
Content-Type: application/json
|
|
Authorization: Bearer <token>
|
|
X-Tenant-ID: <tenant-id>
|
|
X-Client-Version: 1.0.0
|
|
```
|
|
|
|
### Gestão de Tokens
|
|
- **JWT**: Bearer tokens para autenticação
|
|
- **Refresh**: Renovação automática de tokens
|
|
- **Tenant**: Multi-tenancy via headers
|
|
|
|
## 📱 Recursos de UI/UX
|
|
|
|
### Angular Material
|
|
Componentes Material Design integrados:
|
|
- Tables com paginação otimizada para mobile
|
|
- Forms com validação responsiva
|
|
- Navigation com sidenav adaptativo
|
|
- Cards e layouts responsivos
|
|
|
|
### Sistema de Abas Avançado
|
|
- **Tab System**: Gerenciamento inteligente de abas de edição
|
|
- **Mobile First**: Títulos otimizados automaticamente para mobile
|
|
- **Estado Persistente**: Controle de modificações não salvas
|
|
- **Limite Inteligente**: Máximo configurável de abas simultâneas
|
|
|
|
### Data-Table Responsiva
|
|
- **Header Adaptativo**: Layout reorganizado em mobile (duas linhas)
|
|
- **Paginação Compacta**: Texto reduzido e controles otimizados
|
|
- **Edge-to-Edge**: Aproveitamento máximo da tela em mobile
|
|
- **Filtros Inteligentes**: Sistema expansível para dispositivos móveis
|
|
|
|
### PWA (Progressive Web App) ✅ NOVO
|
|
Implementação completa de Progressive Web App com funcionalidades nativas:
|
|
|
|
#### Funcionalidades Principais
|
|
- **Instalação Nativa**: Prompt automático para instalar como app
|
|
- **Updates Automáticos**: Notificações de novas versões disponíveis
|
|
- **Offline Ready**: Service Worker configurado para cache
|
|
- **Notificações Visuais**: Interface responsiva para interações PWA
|
|
- **Debug Tools**: Painel de desenvolvimento para testes
|
|
- **Cross-Platform**: Suporte completo para desktop e mobile
|
|
|
|
#### Estrutura de Implementação
|
|
|
|
**Serviços PWA:**
|
|
```typescript
|
|
// PWAService - Gerenciamento principal
|
|
@Injectable({ providedIn: 'root' })
|
|
export class PWAService {
|
|
// Observables para estado PWA
|
|
public installPromptAvailable$: Observable<boolean>
|
|
public updateAvailable$: Observable<boolean>
|
|
|
|
// Métodos principais
|
|
public async activateUpdate(): Promise<void>
|
|
public async showInstallPrompt(): Promise<boolean>
|
|
public async checkForUpdate(): Promise<boolean>
|
|
|
|
// Verificações de estado
|
|
public isInstalledPWA(): boolean
|
|
public isPWASupported(): boolean
|
|
}
|
|
```
|
|
|
|
**Componente de Notificações:**
|
|
```typescript
|
|
// PWANotificationsComponent - Interface visual
|
|
@Component({
|
|
selector: 'app-pwa-notifications',
|
|
standalone: true
|
|
})
|
|
export class PWANotificationsComponent {
|
|
showUpdateNotification = false;
|
|
showInstallNotification = false;
|
|
showDebugInfo = false; // ✅ Desabilitado para produção (padrão)
|
|
}
|
|
```
|
|
|
|
#### Configuração e Setup
|
|
|
|
**1. Service Worker Configuration** (`ngsw-config.json`):
|
|
```json
|
|
{
|
|
"index": "/index.html",
|
|
"assetGroups": [
|
|
{
|
|
"name": "app",
|
|
"installMode": "prefetch",
|
|
"resources": {
|
|
"files": ["/favicon.ico", "/index.html", "/manifest.webmanifest", "/*.css", "/*.js"]
|
|
}
|
|
},
|
|
{
|
|
"name": "assets",
|
|
"installMode": "lazy",
|
|
"updateMode": "prefetch",
|
|
"resources": {
|
|
"files": ["/**/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
**2. Manifest PWA** (`manifest.webmanifest`):
|
|
```json
|
|
{
|
|
"name": "IDT App - Gestão Inteligente",
|
|
"short_name": "IDT App",
|
|
"display": "standalone",
|
|
"orientation": "portrait-primary",
|
|
"theme_color": "#FFC82E",
|
|
"background_color": "#FFFFFF",
|
|
"categories": ["business", "productivity", "utilities"],
|
|
"icons": [/* Ícones de 72x72 até 512x512 */]
|
|
}
|
|
```
|
|
|
|
**3. Build Configuration** (`angular.json`):
|
|
```json
|
|
{
|
|
"configurations": {
|
|
"production": {
|
|
"serviceWorker": "projects/idt_app/ngsw-config.json",
|
|
"budgets": [{"type": "initial", "maximumWarning": "4mb", "maximumError": "5mb"}]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Fluxos de Funcionamento
|
|
|
|
**Fluxo de Atualização:**
|
|
1. Service Worker detecta nova versão disponível
|
|
2. PWAService emite evento via Observable
|
|
3. PWANotificationsComponent exibe notificação
|
|
4. Usuário clica "Atualizar agora"
|
|
5. Service Worker ativa nova versão e recarrega app
|
|
|
|
**Fluxo de Instalação:**
|
|
1. Browser dispara evento `beforeinstallprompt`
|
|
2. PWAService intercepta e armazena evento
|
|
3. Exibe notificação de instalação
|
|
4. Usuário clica "Instalar"
|
|
5. Mostra dialog nativo do browser
|
|
6. Detecta instalação via `appinstalled`
|
|
|
|
#### Interface Responsiva
|
|
|
|
**Desktop - Notificações no canto superior direito:**
|
|
```scss
|
|
.pwa-notification {
|
|
position: fixed;
|
|
top: 80px;
|
|
right: 20px;
|
|
max-width: 400px;
|
|
}
|
|
```
|
|
|
|
**Mobile - Bottom sheet acima do footer menu:**
|
|
```scss
|
|
@media (max-width: 768px) {
|
|
.pwa-notification {
|
|
bottom: 80px; /* Acima do mobile footer */
|
|
left: 10px;
|
|
right: 10px;
|
|
max-width: none;
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Suporte por Plataforma
|
|
|
|
**Desktop (Chrome, Edge, Firefox):**
|
|
- ✅ Prompt de instalação automático
|
|
- ✅ Ícone na barra de tarefas
|
|
- ✅ Janela standalone
|
|
- ✅ Notificações de update
|
|
|
|
**Mobile (Android):**
|
|
- ✅ Add to Home Screen
|
|
- ✅ Splash screen personalizada
|
|
- ✅ Tema da status bar (#FFC82E)
|
|
- ✅ Orientação portrait
|
|
|
|
**iOS (Safari):**
|
|
- ✅ Add to Home Screen (manual)
|
|
- ✅ Meta tags específicas
|
|
- ⚠️ Limitações do Safari PWA
|
|
|
|
#### Debug e Teste
|
|
|
|
**Debug Panel** (desabilitado por padrão, comentado para reativação):
|
|
```typescript
|
|
// 🔧 DEBUG PWA - Painel de desenvolvimento
|
|
// showDebugInfo = true; // ✅ Habilitar para desenvolvimento/testes
|
|
showDebugInfo = false; // ✅ Desabilitado para produção (padrão)
|
|
```
|
|
|
|
**Informações exibidas:**
|
|
- PWA Suportado: ✅/❌
|
|
- PWA Instalado: ✅/❌
|
|
- Pode Instalar: ✅/❌
|
|
- Update Disponível: ✅/❌
|
|
|
|
**Console Logs informativos:**
|
|
```typescript
|
|
console.log('🚀 IDT App inicializado');
|
|
console.log('📱 PWA Suportado:', this.isPWASupported());
|
|
console.log('🏠 PWA Instalado:', this.isInstalledPWA());
|
|
console.log('🔄 Nova versão disponível!');
|
|
console.log('📲 Prompt de instalação PWA disponível');
|
|
```
|
|
|
|
#### Comandos de Teste
|
|
|
|
**Desenvolvimento PWA:**
|
|
```bash
|
|
# Build de produção (necessário para Service Worker)
|
|
npm run build:prafrota
|
|
|
|
# Servir com HTTPS (necessário para PWA)
|
|
npx http-server dist/idt_app -p 8080 --ssl
|
|
|
|
# Acessar: https://localhost:8080
|
|
```
|
|
|
|
**Testar Updates:**
|
|
```bash
|
|
# 1. Build inicial
|
|
npm run build:prafrota
|
|
|
|
# 2. Alterar código (ex: adicionar console.log)
|
|
|
|
# 3. Build novamente
|
|
npm run build:prafrota
|
|
|
|
# 4. Service Worker detectará automaticamente a mudança
|
|
```
|
|
|
|
**DevTools - Verificações:**
|
|
- **Application > Manifest**: Validar configurações PWA
|
|
- **Application > Service Workers**: Status do SW
|
|
- **Lighthouse**: Audit PWA score (esperado: 90-100/100)
|
|
- **Network > Offline**: Testar funcionamento offline
|
|
|
|
#### Métricas de Performance
|
|
|
|
**Bundle Impact:**
|
|
```
|
|
PWA Service: ~3kB gzipped
|
|
PWA Component: ~2kB gzipped
|
|
Service Worker: ~15kB (Angular SW)
|
|
Total Impact: ~20kB
|
|
```
|
|
|
|
**Lighthouse PWA Criteria:**
|
|
- ✅ Manifest válido
|
|
- ✅ Service Worker registrado
|
|
- ✅ Ícones adequados (72px-512px)
|
|
- ✅ HTTPS em produção
|
|
- ✅ Viewport responsivo
|
|
- ✅ Splash screen configurada
|
|
- ✅ Theme color definido
|
|
|
|
#### Futuras Melhorias
|
|
|
|
**Push Notifications:**
|
|
- Integração com Firebase Cloud Messaging
|
|
- Notificações de sistema
|
|
- Badge counts no ícone
|
|
|
|
**Offline Advanced:**
|
|
- Cache de dados críticos de API
|
|
- Background sync
|
|
- Indicador de status de conectividade
|
|
|
|
**App Shortcuts:**
|
|
- Quick actions no ícone do app
|
|
- Jump lists personalizadas
|
|
- Context menus
|
|
|
|
### Otimizações Mobile Gerais
|
|
- **Breakpoint**: ≤ 768px para mobile
|
|
- **Touch-Friendly**: Controles adequados para toque
|
|
- **Edge-to-Edge**: Layouts que aproveitam toda a tela
|
|
- **Responsive Typography**: Textos adaptados para cada dispositivo
|
|
- **PWA Mobile**: Interface nativa com splash screen e tema personalizado
|
|
- **Navigation**: Bottom sheets e drawers adaptivos
|
|
- **Performance**: Lazy loading e otimizações específicas para mobile
|
|
|
|
### 🔒 Prevenção de Zoom Mobile ✅ NOVO
|
|
Implementação completa para experiência nativa sem zoom indesejado:
|
|
|
|
#### Funcionalidades Implementadas
|
|
- **Double-tap Prevention**: Bloqueia zoom por dois toques
|
|
- **Pinch Prevention**: Desabilita zoom por dois dedos
|
|
- **Keyboard Zoom Prevention**: Previne Ctrl+/- no desktop
|
|
- **Pull-to-refresh Control**: Gerencia refresh contextual
|
|
- **iOS Optimization**: Font-size 16px para prevenir auto-zoom
|
|
|
|
#### Configuração Técnica
|
|
|
|
**1. Meta Viewport** (index.html):
|
|
```html
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
|
<meta name="format-detection" content="telephone=no">
|
|
<meta name="mobile-web-app-capable" content="yes">
|
|
<meta name="apple-touch-fullscreen" content="yes">
|
|
```
|
|
|
|
**2. CSS Prevention** (app.scss):
|
|
```scss
|
|
html, body {
|
|
touch-action: manipulation; /* Previne pinch/double-tap */
|
|
-webkit-touch-callout: none;
|
|
-webkit-user-select: none;
|
|
user-select: none;
|
|
-webkit-tap-highlight-color: transparent;
|
|
}
|
|
|
|
/* Permite seleção em inputs */
|
|
input, textarea, select, [contenteditable] {
|
|
user-select: text;
|
|
font-size: 16px !important; /* Previne auto-zoom iOS */
|
|
}
|
|
```
|
|
|
|
**3. JavaScript Service** (MobileBehaviorService):
|
|
```typescript
|
|
@Injectable({ providedIn: 'root' })
|
|
export class MobileBehaviorService {
|
|
// Prevenção automática de zoom
|
|
// Otimização de touch
|
|
// Controle de pull-to-refresh
|
|
// Detecção de dispositivo mobile
|
|
}
|
|
```
|
|
|
|
#### Comportamentos Controlados
|
|
|
|
**Zoom Prevention:**
|
|
- ❌ Double-tap zoom
|
|
- ❌ Pinch zoom (dois dedos)
|
|
- ❌ Ctrl+scroll zoom
|
|
- ❌ Keyboard zoom (Ctrl +/-)
|
|
|
|
**Preservado:**
|
|
- ✅ Scroll vertical/horizontal
|
|
- ✅ Seleção de texto em inputs
|
|
- ✅ Navegação por touch
|
|
- ✅ Swipe gestures em carousels
|
|
|
|
**Mobile Experience:**
|
|
- ✅ Experiência nativa sem zoom
|
|
- ✅ Touch-action otimizado
|
|
- ✅ 300ms delay removido
|
|
- ✅ Safe areas respeitadas
|
|
- ✅ PWA standalone optimized
|
|
|
|
## 🧪 Testes e Qualidade
|
|
|
|
### Estrutura de Testes
|
|
- **Unit Tests**: Jasmine + Karma
|
|
- **E2E Tests**: Protractor/Cypress (configuração futura)
|
|
- **Linting**: ESLint + Angular ESLint
|
|
|
|
### Code Quality
|
|
- **TypeScript**: Tipagem estrita
|
|
- **Interfaces**: Contratos bem definidos
|
|
- **Services**: Injeção de dependência
|
|
- **Observables**: Programação reativa com RxJS
|
|
|
|
## 🚀 Deploy e Build
|
|
|
|
### Scripts de Build
|
|
- **Development**: `ng serve`
|
|
- **Production**: `ng build --configuration=production`
|
|
- **Specific Projects**: Scripts individuais por projeto
|
|
|
|
### Otimizações
|
|
- **Tree Shaking**: Remoção de código não utilizado
|
|
- **Lazy Loading**: Carregamento sob demanda
|
|
- **Service Workers**: PWA capabilities
|
|
|
|
## 📚 Documentação Adicional
|
|
|
|
### Links Úteis
|
|
- [Angular Documentation](https://angular.io/docs)
|
|
- [Angular Material](https://material.angular.io/)
|
|
- [RxJS Documentation](https://rxjs.dev/)
|
|
- [Leaflet Documentation](https://leafletjs.com/)
|
|
|
|
### Documentação PWA
|
|
- **PWA_IMPLEMENTATION.md**: Guia técnico completo da implementação PWA (400+ linhas)
|
|
- **PWA_QUICK_START.md**: Guia rápido para desenvolvimento e troubleshooting PWA
|
|
- **Service Worker**: Configuração avançada em `ngsw-config.json`
|
|
- **Manifest**: Especificações PWA em `manifest.webmanifest`
|
|
|
|
### Padrões de Arquitetura ✅ NOVO
|
|
- **PATTERNS_INDEX.md**: Índice centralizado de todos os padrões documentados
|
|
- **APP_COMPONENT_PATTERN.md**: Padrão de integração PWA/Mobile no app.component.ts
|
|
- **MOBILE_ZOOM_PREVENTION.md**: Implementação completa de prevenção de zoom mobile
|
|
- **Tab System**: Sistema avançado de abas para edição com gestão de estado
|
|
- **Data Table**: Componentes responsivos com otimizações mobile
|
|
|
|
### Patterns e Best Practices
|
|
- **DDD**: Domain Driven Design
|
|
- **SOLID**: Princípios de desenvolvimento
|
|
- **Reactive Programming**: RxJS patterns
|
|
- **Component Communication**: Input/Output, Services, State Management
|
|
- **PWA Best Practices**: Offline-first, installable, reliable
|
|
|
|
---
|
|
|
|
*Este documento serve como referência central para o desenvolvimento e manutenção do projeto Angular workspace. Mantenha-o atualizado conforme as mudanças na arquitetura e funcionalidades.*
|
|
|
|
**Última atualização**: Janeiro 2025 - Adicionada implementação completa PWA com notificações automáticas, prompts de instalação e documentação técnica detalhada. |