# 📊 Dashboard ERP SAAS PraFrota
## Sistema de Indicadores e KPIs para Gestão de Frota

---

## 🎯 Visão Geral

O Dashboard PraFrota é o centro de controle operacional que oferece visibilidade completa sobre a performance da frota, eficiência das rotas, custos operacionais e indicadores financeiros em tempo real.

---

## 📈 KPIs Estratégicos por Categoria

### 🚚 **1. OPERACIONAL - Frota e Veículos**

#### 📊 KPIs Principais:
- **Taxa de Utilização da Frota** 
  - `(Veículos em Operação / Total de Veículos) × 100`
  - Meta: > 85%
  - Período: Tempo real, diário, mensal

- **Disponibilidade Operacional**
  - `(Veículos Disponíveis / Total de Veículos) × 100`
  - Meta: > 90%
  - Exclui: Manutenção, acidentes, licenciamento

- **Tempo Médio de Inatividade**
  - Média de horas paradas por veículo
  - Meta: < 2 horas/dia
  - Inclui: Manutenção preventiva/corretiva

- **Quilometragem por Veículo**
  - KM rodados por período
  - Comparativo: Planejado vs Realizado
  - Análise de eficiência por modelo/ano

#### 📊 Widgets Visuais:
```typescript
interface FleetKPIs {
  totalVehicles: number;
  activeVehicles: number;
  maintenanceVehicles: number;
  availableVehicles: number;
  utilizationRate: number;
  averageKmPerVehicle: number;
  fuelEfficiencyAverage: number;
}
```

### 🛣️ **2. LOGÍSTICA - Rotas e Entregas**

#### 📊 KPIs Principais:
- **Taxa de Conclusão de Rotas**
  - `(Rotas Completadas / Total de Rotas) × 100`
  - Meta: > 95%
  - Segmentação: Por tipo (First Mile, Line Haul, Last Mile)

- **Pontualidade de Entregas**
  - `(Entregas no Prazo / Total de Entregas) × 100`
  - Meta: > 90%
  - SLA por tipo de cliente

- **Tempo Médio de Rota**
  - Comparativo: Planejado vs Realizado
  - Análise por distância e tipo de carga
  - Identificação de gargalos

- **Taxa de Ocupação de Carga**
  - `(Peso/Volume Transportado / Capacidade Total) × 100`
  - Meta: > 80%
  - Otimização de carregamento

- **Rotas em Atraso**
  - Quantidade e percentual de rotas atrasadas
  - Tempo médio de atraso
  - Principais causas identificadas

#### 📊 Widgets Visuais:
```typescript
interface RoutesKPIs {
  totalRoutes: number;
  completedRoutes: number;
  inProgressRoutes: number;
  delayedRoutes: number;
  completionRate: number;
  onTimeDeliveryRate: number;
  averageRouteTime: number;
  loadUtilizationRate: number;
}
```

### 💰 **3. FINANCEIRO - Custos e Receitas**

#### 📊 KPIs Principais:
- **Custo por Quilômetro**
  - `(Custos Totais / KM Rodados)`
  - Segmentação: Combustível, manutenção, pneus, pedágio
  - Comparativo mensal e anual

- **Receita por Rota**
  - Valor médio faturado por entrega
  - Margem de contribuição por tipo de rota
  - Análise de rentabilidade por cliente

- **ROI da Frota**
  - `(Receita - Custos) / Investimento × 100`
  - Por veículo e por período
  - Análise de payback

- **Custo de Combustível**
  - Consumo médio por veículo
  - Variação de preços por região
  - Eficiência energética

- **Custos de Manutenção**
  - Preventiva vs Corretiva
  - Custo por veículo/km
  - Previsão de gastos

#### 📊 Widgets Visuais:
```typescript
interface FinancialKPIs {
  totalRevenue: number;
  totalCosts: number;
  profitMargin: number;
  costPerKm: number;
  revenuePerRoute: number;
  fuelCosts: number;
  maintenanceCosts: number;
  fleetROI: number;
}
```

### 👨‍💼 **4. RECURSOS HUMANOS - Motoristas**

#### 📊 KPIs Principais:
- **Produtividade por Motorista**
  - Entregas realizadas por período
  - KM rodados por motorista
  - Tempo de trabalho efetivo

- **Taxa de Acidentes**
  - `(Acidentes / KM Rodados) × 1.000.000`
  - Custo médio por acidente
  - Análise de causas principais

- **Pontuação de Condução**
  - Score baseado em telemetria
  - Velocidade, frenagem, aceleração
  - Ranking de motoristas

- **Horas Extras**
  - Percentual sobre horas normais
  - Custo adicional de HE
  - Planejamento vs realizado

#### 📊 Widgets Visuais:
```typescript
interface DriversKPIs {
  totalDrivers: number;
  activeDrivers: number;
  averageProductivity: number;
  accidentRate: number;
  averageDrivingScore: number;
  overtimeHours: number;
  trainingCompliance: number;
}
```

---

## 🎨 Layout do Dashboard

### 📱 **Estrutura Responsiva (4 Colunas → 2 → 1)**

```scss
.dashboard-container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  padding: 20px;

  @media (max-width: 1200px) {
    grid-template-columns: repeat(2, 1fr);
  }

  @media (max-width: 768px) {
    grid-template-columns: 1fr;
  }
}
```

### 🎯 **Seções do Dashboard**

#### 1. **Header com Resumo Executivo**
```html
<div class="executive-summary">
  <div class="kpi-card highlight">
    <h3>Frota Ativa</h3>
    <div class="value">{{ activeFleetCount }}/{{ totalFleetCount }}</div>
    <div class="trend" [ngClass]="getTrendClass('fleet')">
      <i class="fas fa-arrow-up"></i> +5.2%
    </div>
  </div>
  
  <div class="kpi-card highlight">
    <h3>Rotas Hoje</h3>
    <div class="value">{{ todayRoutesCompleted }}/{{ todayRoutesTotal }}</div>
    <div class="progress-bar">
      <div class="progress" [style.width.%]="todayCompletionRate"></div>
    </div>
  </div>
  
  <div class="kpi-card highlight">
    <h3>Receita Mensal</h3>
    <div class="value">{{ monthlyRevenue | currency:'BRL' }}</div>
    <div class="target">Meta: {{ monthlyTarget | currency:'BRL' }}</div>
  </div>
</div>
```

#### 2. **Gráficos Operacionais**
```html
<div class="charts-section">
  <!-- Utilização da Frota - Donut Chart -->
  <div class="chart-card">
    <h4>Utilização da Frota</h4>
    <canvas #fleetUtilizationChart></canvas>
    <div class="chart-legend">
      <span class="legend-item active">Em Operação ({{ activeVehicles }})</span>
      <span class="legend-item maintenance">Manutenção ({{ maintenanceVehicles }})</span>
      <span class="legend-item idle">Parados ({{ idleVehicles }})</span>
    </div>
  </div>

  <!-- Performance de Rotas - Line Chart -->
  <div class="chart-card">
    <h4>Performance de Rotas (7 dias)</h4>
    <canvas #routesPerformanceChart></canvas>
  </div>

  <!-- Custos por Categoria - Bar Chart -->
  <div class="chart-card">
    <h4>Custos Operacionais</h4>
    <canvas #costsBreakdownChart></canvas>
  </div>

  <!-- Mapa de Rotas Ativas -->
  <div class="chart-card map-card">
    <h4>Rotas Ativas</h4>
    <div class="map-container">
      <google-map
        [center]="mapCenter"
        [zoom]="mapZoom"
        [options]="mapOptions">
        <map-marker
          *ngFor="let route of activeRoutes"
          [position]="route.currentLocation"
          [options]="getMarkerOptions(route)">
        </map-marker>
      </google-map>
    </div>
  </div>
</div>
```

#### 3. **Tabelas de Dados**
```html
<div class="data-tables-section">
  <!-- Top 5 Motoristas -->
  <div class="table-card">
    <h4>Top Motoristas (Produtividade)</h4>
    <table class="performance-table">
      <thead>
        <tr>
          <th>Motorista</th>
          <th>Entregas</th>
          <th>KM</th>
          <th>Score</th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let driver of topDrivers">
          <td>{{ driver.name }}</td>
          <td>{{ driver.deliveries }}</td>
          <td>{{ driver.kilometers }}</td>
          <td>
            <span class="score-badge" [ngClass]="getScoreClass(driver.score)">
              {{ driver.score }}
            </span>
          </td>
        </tr>
      </tbody>
    </table>
  </div>

  <!-- Rotas Críticas -->
  <div class="table-card">
    <h4>Rotas em Atraso</h4>
    <table class="critical-routes-table">
      <thead>
        <tr>
          <th>Rota</th>
          <th>Motorista</th>
          <th>Destino</th>
          <th>Atraso</th>
          <th>Ação</th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let route of delayedRoutes" class="delayed-row">
          <td>{{ route.routeNumber }}</td>
          <td>{{ route.driverName }}</td>
          <td>{{ route.destination }}</td>
          <td class="delay-time">{{ route.delayMinutes }}min</td>
          <td>
            <button class="btn btn-sm btn-warning" (click)="contactDriver(route)">
              <i class="fas fa-phone"></i>
            </button>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</div>
```

#### 4. **Alertas e Notificações**
```html
<div class="alerts-section">
  <div class="alert-card" *ngFor="let alert of criticalAlerts" 
       [ngClass]="'alert-' + alert.severity">
    <div class="alert-icon">
      <i class="fas" [ngClass]="getAlertIcon(alert.type)"></i>
    </div>
    <div class="alert-content">
      <h5>{{ alert.title }}</h5>
      <p>{{ alert.message }}</p>
      <small>{{ alert.timestamp | date:'dd/MM/yyyy HH:mm' }}</small>
    </div>
    <div class="alert-actions">
      <button class="btn btn-sm btn-primary" (click)="resolveAlert(alert)">
        Resolver
      </button>
    </div>
  </div>
</div>
```

---

## 🔧 Implementação Técnica

### 📊 **Dashboard Component**

```typescript
@Component({
  selector: 'app-dashboard',
  standalone: true,
  imports: [CommonModule, GoogleMapsModule, NgChartsModule],
  templateUrl: './dashboard.component.html',
  styleUrl: './dashboard.component.scss'
})
export class DashboardComponent implements OnInit, OnDestroy {
  // KPIs Data
  fleetKPIs: FleetKPIs = {};
  routesKPIs: RoutesKPIs = {};
  financialKPIs: FinancialKPIs = {};
  driversKPIs: DriversKPIs = {};

  // Charts Data
  fleetUtilizationData: ChartData = {};
  routesPerformanceData: ChartData = {};
  costsBreakdownData: ChartData = {};

  // Tables Data
  topDrivers: Driver[] = [];
  delayedRoutes: Route[] = [];
  criticalAlerts: Alert[] = [];

  // Real-time Updates
  private updateInterval: any;
  private websocketConnection: WebSocketSubject<any>;

  constructor(
    private dashboardService: DashboardService,
    private websocketService: WebSocketService,
    private cdr: ChangeDetectorRef
  ) {}

  ngOnInit() {
    this.loadDashboardData();
    this.setupRealTimeUpdates();
    this.startPeriodicUpdates();
  }

  ngOnDestroy() {
    if (this.updateInterval) {
      clearInterval(this.updateInterval);
    }
    this.websocketConnection?.complete();
  }

  private loadDashboardData() {
    forkJoin({
      fleet: this.dashboardService.getFleetKPIs(),
      routes: this.dashboardService.getRoutesKPIs(),
      financial: this.dashboardService.getFinancialKPIs(),
      drivers: this.dashboardService.getDriversKPIs(),
      alerts: this.dashboardService.getCriticalAlerts()
    }).subscribe({
      next: (data) => {
        this.fleetKPIs = data.fleet;
        this.routesKPIs = data.routes;
        this.financialKPIs = data.financial;
        this.driversKPIs = data.drivers;
        this.criticalAlerts = data.alerts;
        
        this.updateCharts();
        this.cdr.detectChanges();
      },
      error: (error) => {
        console.error('Erro ao carregar dashboard:', error);
        this.loadFallbackData();
      }
    });
  }

  private setupRealTimeUpdates() {
    this.websocketConnection = this.websocketService.connect('/dashboard-updates');
    
    this.websocketConnection.subscribe({
      next: (update) => {
        this.handleRealTimeUpdate(update);
      },
      error: (error) => {
        console.error('WebSocket error:', error);
      }
    });
  }

  private handleRealTimeUpdate(update: any) {
    switch (update.type) {
      case 'ROUTE_STATUS_CHANGE':
        this.updateRouteStatus(update.data);
        break;
      case 'VEHICLE_STATUS_CHANGE':
        this.updateVehicleStatus(update.data);
        break;
      case 'NEW_ALERT':
        this.addAlert(update.data);
        break;
      case 'KPI_UPDATE':
        this.updateKPIs(update.data);
        break;
    }
    this.cdr.detectChanges();
  }

  private startPeriodicUpdates() {
    // Atualizar dados a cada 5 minutos
    this.updateInterval = setInterval(() => {
      this.loadDashboardData();
    }, 5 * 60 * 1000);
  }

  // Métodos de utilidade
  getTrendClass(kpi: string): string {
    // Lógica para determinar se trend é positivo/negativo
    return 'trend-positive'; // ou 'trend-negative'
  }

  getScoreClass(score: number): string {
    if (score >= 90) return 'score-excellent';
    if (score >= 80) return 'score-good';
    if (score >= 70) return 'score-average';
    return 'score-poor';
  }

  getAlertIcon(type: string): string {
    const icons = {
      'MAINTENANCE': 'fa-wrench',
      'DELAY': 'fa-clock',
      'ACCIDENT': 'fa-exclamation-triangle',
      'FUEL': 'fa-gas-pump',
      'ROUTE': 'fa-route'
    };
    return icons[type] || 'fa-info-circle';
  }

  // Ações do usuário
  contactDriver(route: Route) {
    // Implementar contato com motorista
  }

  resolveAlert(alert: Alert) {
    // Implementar resolução de alerta
  }

  refreshData() {
    this.loadDashboardData();
  }
}
```

### 📊 **Dashboard Service**

```typescript
@Injectable({
  providedIn: 'root'
})
export class DashboardService {
  private apiUrl = `${environment.apiUrl}/dashboard`;

  constructor(private http: HttpClient) {}

  getFleetKPIs(): Observable<FleetKPIs> {
    return this.http.get<FleetKPIs>(`${this.apiUrl}/fleet-kpis`);
  }

  getRoutesKPIs(): Observable<RoutesKPIs> {
    return this.http.get<RoutesKPIs>(`${this.apiUrl}/routes-kpis`);
  }

  getFinancialKPIs(): Observable<FinancialKPIs> {
    return this.http.get<FinancialKPIs>(`${this.apiUrl}/financial-kpis`);
  }

  getDriversKPIs(): Observable<DriversKPIs> {
    return this.http.get<DriversKPIs>(`${this.apiUrl}/drivers-kpis`);
  }

  getCriticalAlerts(): Observable<Alert[]> {
    return this.http.get<Alert[]>(`${this.apiUrl}/alerts`);
  }

  // Dados históricos para gráficos
  getHistoricalData(period: string): Observable<any> {
    return this.http.get(`${this.apiUrl}/historical/${period}`);
  }
}
```

---

## 📊 Dados Mockados para Desenvolvimento

### 🎯 **KPIs Mock Data**

```json
{
  "fleetKPIs": {
    "totalVehicles": 45,
    "activeVehicles": 38,
    "maintenanceVehicles": 4,
    "availableVehicles": 3,
    "utilizationRate": 84.4,
    "averageKmPerVehicle": 287.5,
    "fuelEfficiencyAverage": 8.2
  },
  "routesKPIs": {
    "totalRoutes": 156,
    "completedRoutes": 142,
    "inProgressRoutes": 12,
    "delayedRoutes": 2,
    "completionRate": 91.0,
    "onTimeDeliveryRate": 87.2,
    "averageRouteTime": 4.7,
    "loadUtilizationRate": 78.9
  },
  "financialKPIs": {
    "totalRevenue": 487650.00,
    "totalCosts": 312420.00,
    "profitMargin": 35.9,
    "costPerKm": 2.85,
    "revenuePerRoute": 3126.28,
    "fuelCosts": 89450.00,
    "maintenanceCosts": 45780.00,
    "fleetROI": 24.7
  },
  "driversKPIs": {
    "totalDrivers": 52,
    "activeDrivers": 38,
    "averageProductivity": 8.7,
    "accidentRate": 0.12,
    "averageDrivingScore": 82.5,
    "overtimeHours": 156.5,
    "trainingCompliance": 94.2
  }
}
```

---

## 🎨 Estilos CSS

```scss
.dashboard-container {
  padding: 20px;
  background: #f8f9fa;
  min-height: 100vh;

  .executive-summary {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 16px;
    margin-bottom: 24px;

    .kpi-card {
      background: white;
      border-radius: 8px;
      padding: 20px;
      box-shadow: 0 2px 4px rgba(0,0,0,0.1);
      border-left: 4px solid #007bff;

      &.highlight {
        border-left-color: #28a745;
      }

      h3 {
        font-size: 14px;
        color: #6c757d;
        margin-bottom: 8px;
        text-transform: uppercase;
      }

      .value {
        font-size: 28px;
        font-weight: bold;
        color: #212529;
        margin-bottom: 8px;
      }

      .trend {
        font-size: 12px;
        font-weight: 500;

        &.trend-positive {
          color: #28a745;
        }

        &.trend-negative {
          color: #dc3545;
        }
      }

      .progress-bar {
        width: 100%;
        height: 6px;
        background: #e9ecef;
        border-radius: 3px;
        overflow: hidden;

        .progress {
          height: 100%;
          background: #28a745;
          transition: width 0.3s ease;
        }
      }
    }
  }

  .charts-section {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
    gap: 16px;
    margin-bottom: 24px;

    .chart-card {
      background: white;
      border-radius: 8px;
      padding: 20px;
      box-shadow: 0 2px 4px rgba(0,0,0,0.1);

      h4 {
        margin-bottom: 16px;
        color: #212529;
      }

      &.map-card {
        .map-container {
          height: 300px;
          border-radius: 4px;
          overflow: hidden;
        }
      }
    }
  }

  .data-tables-section {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
    gap: 16px;
    margin-bottom: 24px;

    .table-card {
      background: white;
      border-radius: 8px;
      padding: 20px;
      box-shadow: 0 2px 4px rgba(0,0,0,0.1);

      table {
        width: 100%;
        border-collapse: collapse;

        th, td {
          padding: 12px 8px;
          text-align: left;
          border-bottom: 1px solid #e9ecef;
        }

        th {
          background: #f8f9fa;
          font-weight: 600;
          color: #495057;
        }

        .score-badge {
          padding: 4px 8px;
          border-radius: 12px;
          font-size: 12px;
          font-weight: 500;

          &.score-excellent {
            background: #d4edda;
            color: #155724;
          }

          &.score-good {
            background: #cce5ff;
            color: #004085;
          }

          &.score-average {
            background: #fff3cd;
            color: #856404;
          }

          &.score-poor {
            background: #f8d7da;
            color: #721c24;
          }
        }

        .delayed-row {
          background: #fff3cd;

          .delay-time {
            color: #856404;
            font-weight: 600;
          }
        }
      }
    }
  }

  .alerts-section {
    .alert-card {
      background: white;
      border-radius: 8px;
      padding: 16px;
      margin-bottom: 12px;
      box-shadow: 0 2px 4px rgba(0,0,0,0.1);
      display: flex;
      align-items: center;
      gap: 16px;

      &.alert-critical {
        border-left: 4px solid #dc3545;
      }

      &.alert-warning {
        border-left: 4px solid #ffc107;
      }

      &.alert-info {
        border-left: 4px solid #17a2b8;
      }

      .alert-icon {
        font-size: 24px;
        color: #6c757d;
      }

      .alert-content {
        flex: 1;

        h5 {
          margin-bottom: 4px;
          color: #212529;
        }

        p {
          margin-bottom: 4px;
          color: #6c757d;
        }

        small {
          color: #adb5bd;
        }
      }
    }
  }
}

// Responsividade
@media (max-width: 768px) {
  .dashboard-container {
    padding: 12px;

    .charts-section,
    .data-tables-section {
      grid-template-columns: 1fr;
    }

    .executive-summary {
      grid-template-columns: 1fr;
    }
  }
}
```

---

## 🚀 Próximos Passos

### 1. **Implementação por Fases**
- **Fase 1**: KPIs básicos + gráficos simples
- **Fase 2**: Mapa em tempo real + alertas
- **Fase 3**: Machine Learning para previsões
- **Fase 4**: Dashboards personalizáveis por usuário

### 2. **Integrações Necessárias**
- WebSocket para dados em tempo real
- Google Maps API para visualização
- Chart.js ou D3.js para gráficos
- Push notifications para alertas críticos

### 3. **Otimizações de Performance**
- Cache de dados com TTL
- Lazy loading de componentes
- Paginação server-side
- Compressão de dados WebSocket

---

## 📱 Configuração no Sidebar

```typescript
// Adicionar ao menu principal
{
  id: 'dashboard',
  label: 'Dashboard',
  icon: 'fa-tachometer-alt',
  route: '/dashboard',
  order: 1, // Primeiro item do menu
  permissions: ['DASHBOARD_VIEW']
}
```

Este dashboard fornece uma visão 360° da operação, permitindo tomada de decisões baseada em dados e monitoramento proativo da performance da frota. 📊✨ 