@php
$cards = $dashboard['cards'];
$visibleCards = \App\Support\DashboardTorreCards::visibleMap();
$isVisible = fn (string $key): bool => $visibleCards[$key] ?? true;
$dataInicioLabel = \Illuminate\Support\Carbon::parse($filters['data_inicio'])->format('d/m/Y');
$dataFimLabel = \Illuminate\Support\Carbon::parse($filters['data_fim'])->format('d/m/Y');
$dataLabel = $filters['data_inicio'] === $filters['data_fim']
? $dataInicioLabel
: $dataInicioLabel . ' a ' . $dataFimLabel;
$progress = function (int $done, int $total): int {
return $total > 0 ? min(100, (int) round(($done / $total) * 100)) : 0;
};
$format = fn (int|float $value): string => number_format((float) $value, 0, ',', '.');
$filterQuery = array_filter([
'data' => $filters['data_inicio'],
'filial_id' => $filters['filial_id'],
], fn ($value) => filled($value));
$controleUrl = \App\Filament\Pages\ControleOperacoes::getUrl() . ($filterQuery ? '?' . http_build_query($filterQuery) : '');
$movimentosPorCidade = $dashboard['movimentos_por_cidade'] ?? [];
$maiorVolumeCidade = max(array_column($movimentosPorCidade, 'total') ?: [0]);
$ocorrenciasPorMotivo = $dashboard['ocorrencias_por_motivo'] ?? [];
$maiorVolumeOcorrencia = max(array_column($ocorrenciasPorMotivo, 'total') ?: [0]);
$movimentos = $dashboard['movimentos'] ?? ['abertos' => 0, 'concluidos' => 0, 'ocorrencias' => 0, 'em_rota' => 0, 'total' => 0];
$movimentosAgendados = $dashboard['movimentos_agendados'] ?? ['abertos' => 0, 'concluidos' => 0, 'ocorrencias' => 0, 'em_rota' => 0, 'total' => 0];
$pieSlices = function (array $data): array {
return [
['label' => 'Em aberto', 'value' => (int) ($data['abertos'] ?? 0), 'color' => '#f59e0b'],
['label' => 'Concluidos', 'value' => (int) ($data['concluidos'] ?? 0), 'color' => '#22c55e'],
['label' => 'Ocorrencias', 'value' => (int) ($data['ocorrencias'] ?? 0), 'color' => '#ef4444'],
['label' => 'Em rota', 'value' => (int) ($data['em_rota'] ?? 0), 'color' => '#3b82f6'],
];
};
$pieStyle = function (array $slices): string {
$total = max(array_sum(array_column($slices, 'value')), 0);
if ($total === 0) {
return 'background:#e5e7eb;';
}
$cursor = 0;
$parts = [];
foreach ($slices as $slice) {
$start = $cursor;
$cursor += (($slice['value'] / $total) * 100);
$parts[] = $slice['color'].' '.$start.'% '.$cursor.'%';
}
return 'background:conic-gradient('.implode(', ', $parts).');';
};
$movimentosSlices = $pieSlices($movimentos);
$agendadosSlices = $pieSlices($movimentosAgendados);
$movimentosPieTotal = array_sum(array_column($movimentosSlices, 'value'));
$agendadosPieTotal = array_sum(array_column($agendadosSlices, 'value'));
$evolucaoPct = $progress((int) ($movimentos['concluidos'] ?? 0), max((int) ($movimentos['total'] ?? 0), 0));
$gaugeRotation = -90 + (180 * ($evolucaoPct / 100));
$topCards = [
[
'key' => 'entregas',
'label' => 'Entregas',
'value' => $cards['entregas'],
'done' => $cards['entregas_executadas'],
'total' => $cards['entregas'],
'caption' => 'enderecos atendidos',
'progress_text' => $format($cards['entregas_executadas']).'/'.$format($cards['entregas']).' entregues',
'tone' => 'blue',
'icon' => 'ENT',
],
[
'key' => 'coletas',
'label' => 'Coletas',
'value' => $cards['coletas'],
'done' => $cards['coletas_executadas'],
'total' => $cards['coletas'],
'caption' => 'coletas executadas',
'progress_text' => $format($cards['coletas_executadas']).'/'.$format($cards['coletas']).' coletadas',
'tone' => 'green',
'icon' => 'COL',
],
[
'key' => 'transferencias',
'label' => 'Transferencias',
'value' => $cards['transferencias'],
'done' => $cards['transferencias_concluidas'],
'total' => $cards['transferencias'],
'caption' => 'movimento entre filiais',
'progress_text' => $format($cards['transferencias_concluidas']).'/'.$format($cards['transferencias']).' concluidas',
'tone' => 'purple',
'icon' => 'TRA',
],
[
'key' => 'reentregas',
'label' => 'Reentregas',
'value' => $cards['reentregas'],
'done' => $cards['reentregas_concluidas'],
'total' => $cards['reentregas'],
'caption' => 'tentativas pendentes',
'progress_text' => $format($cards['reentregas_concluidas']).'/'.$format($cards['reentregas']).' concluidas',
'tone' => 'red',
'icon' => 'REE',
],
[
'key' => 'ocorrencias',
'label' => 'Ocorrencias',
'value' => max($cards['ocorrencias_total'] - $cards['ocorrencias_tratadas'], 0),
'done' => $cards['ocorrencias_tratadas'],
'total' => $cards['ocorrencias_total'],
'caption' => 'tratadas / a tratar',
'tone' => 'yellow',
'icon' => 'OCO',
'secondary' => $cards['ocorrencias_tratadas'].' / '.max($cards['ocorrencias_total'] - $cards['ocorrencias_tratadas'], 0),
],
];
$bottomCards = [
[
'key' => 'app_acessos',
'label' => 'Acessos ao aplicativo',
'value' => $cards['motoristas_app'],
'done' => $cards['motoristas_app'],
'total' => $cards['motoristas_operacionais'],
'caption' => 'acesso pelo aplicativo',
'tone' => 'blue',
'icon' => 'APP',
],
[
'key' => 'veiculos_rota',
'label' => 'Veiculos em rota',
'value' => $cards['veiculos_em_rota'],
'done' => $cards['veiculos_em_rota_concluidos'],
'total' => $cards['veiculos_em_rota_total_movimentos'],
'caption' => 'romaneios em rota',
'tone' => 'gray',
'icon' => 'VEI',
],
[
'key' => 'entregas_rota',
'label' => 'Entregas por rota',
'value' => $cards['media_entregas_por_rota'],
'done' => $cards['entregas_por_rota_concluidas'],
'total' => $cards['entregas_por_rota_total'],
'caption' => 'media por veiculo',
'tone' => 'purple',
'icon' => 'ROT',
],
[
'key' => 'custo_viagem',
'label' => 'Custo por viagem',
'value' => 'R$ '.number_format((float) $cards['custo_medio_por_viagem'], 2, ',', '.'),
'done' => (int) round((float) $cards['custo_viagens_total'] * 100),
'total' => max((int) round((float) $cards['custo_viagens_total'] * 100), 1),
'caption' => 'media estimada de custo',
'tone' => 'yellow',
'icon' => 'CUS',
],
[
'key' => 'eficiencia',
'label' => 'Eficiencia da operacao',
'value' => $progress($cards['eficiencia_concluidos'], $cards['eficiencia_total']).'%',
'done' => $cards['eficiencia_concluidos'],
'total' => $cards['eficiencia_total'],
'caption' => 'movimentos concluidos',
'tone' => 'green',
'icon' => 'EFI',
],
[
'key' => 'otif',
'label' => 'OTIF',
'value' => $progress($cards['otif_concluidos'], $cards['otif_total']).'%',
'done' => $cards['otif_concluidos'],
'total' => $cards['otif_total'],
'caption' => 'entregas completas no prazo',
'progress_text' => $format($cards['otif_concluidos']).'/'.$format($cards['otif_total']).' entregas OTIF',
'tone' => 'green',
'icon' => 'OTF',
],
[
'key' => 'entregas_fora_prazo',
'label' => 'Entregas fora do prazo',
'value' => $cards['otif_fora_prazo'],
'done' => $cards['otif_fora_prazo'],
'total' => $cards['otif_entregues'],
'caption' => 'entregas concluidas com atraso',
'progress_text' => $format($cards['otif_fora_prazo']).'/'.$format($cards['otif_entregues']).' entregas fora do prazo',
'tone' => 'red',
'icon' => 'ATR',
],
];
$topCards = collect($topCards)
->filter(fn (array $card): bool => $isVisible($card['key']))
->values();
$bottomCards = collect($bottomCards)
->filter(fn (array $card): bool => $isVisible($card['key']))
->values();
$displayCards = $topCards->concat($bottomCards)->values();
@endphp
@foreach($displayCards as $card)
@php
$pct = $progress($card['done'], $card['total']);
@endphp
{{ $card['icon'] }}
{{ $card['label'] }}
{{ $dataLabel }}
{{ $card['secondary'] ?? (is_numeric($card['value']) ? $format($card['value']) : $card['value']) }}
{{ $card['progress_text'] ?? $card['caption'] }}
{{ $pct }}%
@endforeach
Movimentos
NFs, coletas, reentregas e transferencias
{{ $format($movimentosPieTotal) }}
{{ $format($movimentosPieTotal) }}
@foreach($movimentosSlices as $slice)
{{ $slice['label'] }}
{{ $format($slice['value']) }}
@endforeach
Evolucao operacional
Movimentos ja concluidos
{{ $evolucaoPct }}%
{{ $evolucaoPct }}%
{{ $format($movimentos['concluidos'] ?? 0) }} concluidos
Agendados
Movimentos com data e hora de entrega
{{ $format($agendadosPieTotal) }}
{{ $format($agendadosPieTotal) }}
@foreach($agendadosSlices as $slice)
{{ $slice['label'] }}
{{ $format($slice['value']) }}
@endforeach
Ocorrencias pontuadas
Quantidade por motivo de ocorrencia e codigo do cliente
{{ $format(array_sum(array_column($ocorrenciasPorMotivo, 'total'))) }}
@if(count($ocorrenciasPorMotivo))
@foreach($ocorrenciasPorMotivo as $ocorrencia)
@php
$pctOcorrencia = $maiorVolumeOcorrencia > 0 ? max(8, (int) round(($ocorrencia['total'] / $maiorVolumeOcorrencia) * 100)) : 0;
@endphp
{{ $format($ocorrencia['total']) }}
{{ $ocorrencia['motivo'] }}
{{ $ocorrencia['codigo_cliente'] }}
@endforeach
@else
Sem ocorrencias pontuadas no periodo selecionado.
@endif
Movimentos por regiao
Volume de entregas, coletas, reentregas e transferencias por cidade
{{ $dataLabel }}
@forelse($movimentosPorCidade as $cidade)
@php
$pctCidade = $maiorVolumeCidade > 0 ? max(4, (int) round(($cidade['total'] / $maiorVolumeCidade) * 100)) : 0;
@endphp
{{ $cidade['cidade'] }}
{{ $cidade['uf'] }}
{{ $format($cidade['total']) }}
@empty
Sem movimentos no periodo selecionado.
@endforelse
@once
@endonce