257 lines
7.1 KiB
TypeScript
257 lines
7.1 KiB
TypeScript
/**
|
|
* EXEMPLO SIMPLIFICADO - Implementação de Fallback para Dados Mockados
|
|
* Use este exemplo como base para implementar rapidamente o sistema de fallback
|
|
*/
|
|
|
|
import { Injectable } from '@angular/core';
|
|
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
|
import { Observable, of } from 'rxjs';
|
|
import { catchError, map, timeout } from 'rxjs/operators';
|
|
|
|
// Para importar dados mockados, configure tsconfig.json com:
|
|
// "resolveJsonModule": true, "allowSyntheticDefaultImports": true
|
|
// Depois use: import mockData from './ROUTES_MOCK_DATA_COMPLETE.json';
|
|
|
|
// Ou use require() como alternativa:
|
|
// const mockData = require('./ROUTES_MOCK_DATA_COMPLETE.json');
|
|
|
|
// Interface para tipagem das rotas
|
|
interface Route {
|
|
id: string;
|
|
routeNumber: string;
|
|
type: string;
|
|
status: string;
|
|
origin: { address: string };
|
|
destination: { address: string };
|
|
vehiclePlate: string;
|
|
[key: string]: any;
|
|
}
|
|
|
|
@Injectable({
|
|
providedIn: 'root'
|
|
})
|
|
export class RoutesServiceSimple {
|
|
private apiUrl = 'https://prafrota-be-bff-tenant-api.grupopra.tech/api/v1/routes';
|
|
|
|
// Dados mockados inline (substitua pelo import quando configurar o JSON)
|
|
private mockRoutes: Route[] = [
|
|
{
|
|
id: "rt_001",
|
|
routeNumber: "RT-2024-000001",
|
|
type: "firstMile",
|
|
status: "inProgress",
|
|
origin: { address: "Centro de Distribuição - São Paulo, SP" },
|
|
destination: { address: "Rua Augusta, 1000 - São Paulo, SP" },
|
|
vehiclePlate: "TAS4J92"
|
|
},
|
|
// Adicione mais dados mockados aqui ou importe do JSON
|
|
];
|
|
|
|
constructor(private http: HttpClient) {}
|
|
|
|
/**
|
|
* MÉTODO PRINCIPAL - Busca rotas com fallback automático
|
|
*/
|
|
getRoutes(): Observable<any> {
|
|
console.log('🔄 Tentando buscar dados do backend...');
|
|
|
|
return this.http.get(this.apiUrl).pipe(
|
|
timeout(10000), // 10 segundos de timeout
|
|
map(response => {
|
|
console.log('✅ Dados recebidos do backend');
|
|
return {
|
|
data: response,
|
|
source: 'backend',
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
}),
|
|
catchError((error: HttpErrorResponse) => {
|
|
console.warn('⚠️ Backend falhou, usando dados mockados:', error.message);
|
|
|
|
return of({
|
|
data: this.mockRoutes,
|
|
source: 'fallback',
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
})
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Busca rota por ID com fallback
|
|
*/
|
|
getRouteById(id: string): Observable<Route | null> {
|
|
return this.http.get<Route>(`${this.apiUrl}/${id}`).pipe(
|
|
timeout(10000),
|
|
catchError((error: HttpErrorResponse) => {
|
|
console.warn('⚠️ Backend falhou, buscando rota mockada:', error.message);
|
|
|
|
const mockRoute = this.mockRoutes.find((route: Route) => route.id === id);
|
|
return of(mockRoute || null);
|
|
})
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Filtrar dados mockados (para usar quando backend falhar)
|
|
*/
|
|
filterMockData(filters: any = {}): Route[] {
|
|
let filtered = [...this.mockRoutes];
|
|
|
|
// Filtro por tipo
|
|
if (filters.type) {
|
|
filtered = filtered.filter((route: Route) => route.type === filters.type);
|
|
}
|
|
|
|
// Filtro por status
|
|
if (filters.status) {
|
|
filtered = filtered.filter((route: Route) => route.status === filters.status);
|
|
}
|
|
|
|
// Filtro por busca de texto
|
|
if (filters.search) {
|
|
const searchLower = filters.search.toLowerCase();
|
|
filtered = filtered.filter((route: Route) =>
|
|
route.routeNumber.toLowerCase().includes(searchLower) ||
|
|
route.origin.address.toLowerCase().includes(searchLower) ||
|
|
route.destination.address.toLowerCase().includes(searchLower) ||
|
|
route.vehiclePlate.toLowerCase().includes(searchLower)
|
|
);
|
|
}
|
|
|
|
return filtered;
|
|
}
|
|
|
|
/**
|
|
* Verificar se backend está disponível
|
|
*/
|
|
checkBackendHealth(): Observable<boolean> {
|
|
return this.http.get(`${this.apiUrl}/health`).pipe(
|
|
timeout(5000),
|
|
map(() => true),
|
|
catchError(() => of(false))
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* CONFIGURAÇÃO DO TSCONFIG.JSON para importar JSON:
|
|
*
|
|
* {
|
|
* "compilerOptions": {
|
|
* "resolveJsonModule": true,
|
|
* "allowSyntheticDefaultImports": true
|
|
* }
|
|
* }
|
|
*/
|
|
|
|
/**
|
|
* EXEMPLO DE USO NO COMPONENT
|
|
*/
|
|
/*
|
|
export class RoutesComponent {
|
|
routes: Route[] = [];
|
|
isOffline = false;
|
|
dataSource = '';
|
|
|
|
constructor(private routesService: RoutesServiceSimple) {}
|
|
|
|
ngOnInit() {
|
|
this.loadRoutes();
|
|
}
|
|
|
|
loadRoutes() {
|
|
this.routesService.getRoutes().subscribe({
|
|
next: (response) => {
|
|
this.routes = response.data;
|
|
this.isOffline = response.source === 'fallback';
|
|
this.dataSource = response.source;
|
|
|
|
console.log(`📊 Carregadas ${this.routes.length} rotas da fonte: ${this.dataSource}`);
|
|
},
|
|
error: (error) => {
|
|
console.error('❌ Erro ao carregar rotas:', error);
|
|
}
|
|
});
|
|
}
|
|
|
|
retryConnection() {
|
|
console.log('🔄 Tentando reconectar...');
|
|
this.loadRoutes();
|
|
}
|
|
}
|
|
*/
|
|
|
|
/**
|
|
* EXEMPLO DE TEMPLATE HTML
|
|
*/
|
|
/*
|
|
<div class="container">
|
|
<!-- Indicador de Status -->
|
|
<div class="alert" [ngClass]="{
|
|
'alert-success': !isOffline,
|
|
'alert-warning': isOffline
|
|
}">
|
|
<i class="fas" [ngClass]="{
|
|
'fa-wifi': !isOffline,
|
|
'fa-wifi-slash': isOffline
|
|
}"></i>
|
|
|
|
<span *ngIf="!isOffline">Sistema Online - Dados do Servidor</span>
|
|
<span *ngIf="isOffline">Modo Offline - Dados Locais</span>
|
|
|
|
<button
|
|
*ngIf="isOffline"
|
|
class="btn btn-sm btn-primary ms-2"
|
|
(click)="retryConnection()">
|
|
Reconectar
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Lista de Rotas -->
|
|
<div class="row">
|
|
<div class="col-md-4" *ngFor="let route of routes">
|
|
<div class="card mb-3">
|
|
<div class="card-body">
|
|
<h5 class="card-title">{{ route.routeNumber }}</h5>
|
|
<p class="card-text">
|
|
<strong>Tipo:</strong> {{ route.type }}<br>
|
|
<strong>Status:</strong> {{ route.status }}<br>
|
|
<strong>Origem:</strong> {{ route.origin.address }}<br>
|
|
<strong>Destino:</strong> {{ route.destination.address }}<br>
|
|
<strong>Veículo:</strong> {{ route.vehiclePlate }}
|
|
</p>
|
|
<span class="badge" [ngClass]="{
|
|
'bg-success': route.status === 'completed',
|
|
'bg-primary': route.status === 'inProgress',
|
|
'bg-warning': route.status === 'pending',
|
|
'bg-danger': route.status === 'delayed',
|
|
'bg-secondary': route.status === 'cancelled'
|
|
}">
|
|
{{ route.status }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
*/
|
|
|
|
/**
|
|
* INSTRUÇÕES DE IMPLEMENTAÇÃO RÁPIDA:
|
|
*
|
|
* 1. Copie este service para seu projeto
|
|
* 2. Configure tsconfig.json para suportar import de JSON
|
|
* 3. Importe os dados mockados do arquivo JSON
|
|
* 4. Configure a URL da sua API
|
|
* 5. Use o método getRoutes() no seu component
|
|
* 6. Adicione o indicador visual no template
|
|
*
|
|
* VANTAGENS:
|
|
* ✅ Implementação simples e rápida
|
|
* ✅ Fallback automático e transparente
|
|
* ✅ Logs informativos no console
|
|
* ✅ Dados realistas para desenvolvimento
|
|
* ✅ Sistema continua funcionando offline
|
|
* ✅ Tipagem TypeScript correta
|
|
*/
|