@extends('layouts.app') @section('title', 'OS ' . $ordem->numero_os) @section('page_title', 'OS ' . $ordem->numero_os) @section('content') @php $colorMap = [ 'blue' => 'bg-blue-100 text-blue-700', 'indigo' => 'bg-indigo-100 text-indigo-800', 'teal' => 'bg-teal-100 text-teal-800', 'red' => 'bg-red-100 text-red-700', 'orange' => 'bg-orange-100 text-orange-700', 'gray' => 'bg-gray-100 text-gray-700', ]; $badge = $colorMap[$ordem->statusColor()] ?? 'bg-gray-100 text-gray-700'; @endphp
{{-- Cabeçalho --}}

{{ $ordem->numero_os }}

{{ $ordem->statusLabel() }} @if($ordem->finalizado) Finalizado @endif
@if($ordem->solicitacao) Solicitação: {{ $ordem->solicitacao->numero_solicitacao }} @endif Cliente: {{ $ordem->cliente_solicitante }} @if($ordem->pedido_cliente)Pedido / OS Cliente: {{ $ordem->pedido_cliente }}@endif Data: {{ $ordem->data_servico?->format('d/m/Y') }} @if($ordem->operador) Operador: {{ $ordem->operador->name }} @endif
← Voltar 🔒 OS rastreável
{{-- Alertas --}} @if(session('success'))
{{ session('success') }}
@endif @if(session('error'))
{{ session('error') }}
@endif @if($errors->any())
@endif {{-- Linha do tempo operacional --}} @php $timeline = [ ['label'=>'Início da viagem','data'=>$ordem->inicio_viagem_em,'duracao'=>null,'km'=>null,'tipo'=>'vazio'], ['label'=>'Chegada na origem','data'=>$ordem->chegada_origem_em,'duracao'=>$ordem->tempoAteOrigemMinutos(),'km'=>$ordem->km_vazio_ate_origem,'tipo'=>'vazio'], ['label'=>'Saída da origem','data'=>$ordem->saida_origem_em,'duracao'=>$ordem->permanenciaOrigemMinutos(),'km'=>null,'tipo'=>'parada'], ['label'=>'Chegada no destino','data'=>$ordem->chegada_destino_em,'duracao'=>$ordem->transitoDestinoMinutos(),'km'=>$ordem->kmCarregado(),'tipo'=>'carregado'], ['label'=>'Saída do destino','data'=>$ordem->saida_destino_em,'duracao'=>$ordem->permanenciaDestinoMinutos(),'km'=>null,'tipo'=>'parada'], ['label'=>'Ponto de espera','data'=>$ordem->chegada_ponto_espera_em,'duracao'=>$ordem->tempoPosDestinoMinutos(),'km'=>$ordem->km_vazio_pos_destino,'tipo'=>'vazio'], ]; $primeiroPendente = collect($timeline)->search(fn ($etapa) => !$etapa['data']); $primeiroPendente = $primeiroPendente === false ? count($timeline) : $primeiroPendente; @endphp

Linha do Tempo Operacional

Evolução real da viagem, com tempos e quilômetros conhecidos em cada fase.

{{ \App\Models\OrdemServico::formatarDuracao($ordem->tempoOperacaoTotalMinutos()) }} operação {{ $ordem->kmOperacaoConsolidado() !== null ? number_format($ordem->kmOperacaoConsolidado(),3,',','.') . ' km' : '—' }} consolidados
@foreach($timeline as $i => $etapa) @php $concluida = (bool)$etapa['data']; $atual = !$concluida && $i === $primeiroPendente && !in_array($ordem->status, ['concluido','cancelado','negado'], true); $corTexto = $etapa['tipo'] === 'carregado' ? 'text-blue-700' : ($etapa['tipo'] === 'parada' ? 'text-amber-700' : 'text-emerald-700'); @endphp
@if($i < count($timeline)-1)
@endif
{{ $concluida ? '✓' : $i + 1 }}
{{ $etapa['label'] }}
{{ $etapa['data'] ? $etapa['data']->format('d/m H:i') : ($atual ? 'Próxima etapa' : 'Pendente') }}
@if($etapa['duracao'] !== null)
{{ \App\Models\OrdemServico::formatarDuracao($etapa['duracao']) }}
@endif @if($etapa['km'] !== null)
{{ number_format($etapa['km'],3,',','.') }} km
@endif
@endforeach
@if($ordem->percentualKmCarregado() !== null)
Produtivo
{{ number_format($ordem->percentualKmCarregado(),1,',','.') }}%
Vazio
{{ number_format($ordem->percentualKmVazio(),1,',','.') }}%
Parado origem + destino
{{ \App\Models\OrdemServico::formatarDuracao($ordem->tempoParadoMinutos()) }}
Km carregados
{{ number_format($ordem->kmCarregado(),3,',','.') }} km
@endif
{{-- Formulário de edição --}}
@csrf @method('PUT')

Dados da Ordem de Serviço

{{-- Linha 1: Data, Hora, Cliente, Sonda --}}
{{-- Linha 2: Origem → Destino --}}
{{-- Linha 3: Veículo + Carreta --}}

Nenhuma carroceria ativa compatível com este cavalo e com a capacidade necessária.

{{-- Marcos da Viagem / Telemetria --}}

Marcos da Viagem / Telemetria

Preenchimento manual disponível. A mesma estrutura será alimentada futuramente pela integração A52.

@if($ordem->telemetria_fonte) Fonte: {{ match($ordem->telemetria_fonte) { 'a52' => 'A52', 'gps' => 'GPS da frota', 'misto' => 'Múltiplas fontes', default => 'Manual' } }} @endif @if($ordem->a52_referencia) A52: {{ $ordem->a52_referencia }} @else A52 ainda não vinculado @endif
Os marcos devem ser registrados em sequência: Início da viagem → Chegada na origem → Saída da origem → Chegada no destino → Saída do destino. Um marco só é habilitado depois que o anterior estiver informado.
@php $marcosViagem = [ 'inicio_viagem_em' => ['Início da viagem', 'inicioViagem', null], 'chegada_origem_em' => ['Chegada na origem', 'chegadaOrigem', 'inicioViagem'], 'saida_origem_em' => ['Saída da origem', 'saidaOrigem', 'chegadaOrigem'], 'chegada_destino_em' => ['Chegada no destino', 'chegadaDestino', 'saidaOrigem'], 'saida_destino_em' => ['Saída do destino', 'saidaDestino', 'chegadaDestino'], ]; @endphp @foreach($marcosViagem as $campoMarco => [$labelMarco, $modeloMarco, $modeloAnterior])
@if($modeloAnterior)

Informe o marco anterior primeiro.

@endif
@endforeach
@php $temposViagem = [ ['Vazio até origem', $ordem->tempoAteOrigemMinutos()], ['Na origem', $ordem->permanenciaOrigemMinutos()], ['Carregado', $ordem->transitoDestinoMinutos()], ['No destino', $ordem->permanenciaDestinoMinutos()], ['Vazio pós-destino', $ordem->tempoPosDestinoMinutos()], ['Operação total', $ordem->tempoOperacaoTotalMinutos()], ]; @endphp @foreach($temposViagem as [$rotuloTempo, $minutosTempo])
{{ $rotuloTempo }}
{{ \App\Models\OrdemServico::formatarDuracao($minutosTempo) }}
@endforeach
@if($ordem->telemetria_atualizada_em || $ordem->a52_sincronizado_em)
@if($ordem->telemetria_atualizada_em)Telemetria atualizada: {{ $ordem->telemetria_atualizada_em->format('d/m/Y H:i') }}@endif @if($ordem->a52_sincronizado_em)Última sincronização A52: {{ $ordem->a52_sincronizado_em->format('d/m/Y H:i') }}@endif
@endif
{{-- Geolocalização / Km vazios --}}

Geolocalização e Quilometragem sem carga

Coordenadas podem ser informadas manualmente e futuramente recebidas do A52 ou do GPS/rastreador do caminhão.

@if($ordem->geolocalizacao_fonte) Fonte: {{ match($ordem->geolocalizacao_fonte) { 'a52' => 'A52', 'gps' => 'GPS da frota', 'misto' => 'Múltiplas fontes', default => 'Manual' } }} @endif
Origem planejada
@if($ordem->origem_latitude_planejada !== null && $ordem->origem_longitude_planejada !== null) {{ number_format($ordem->origem_latitude_planejada,7,'.','') }}, {{ number_format($ordem->origem_longitude_planejada,7,'.','') }} @else Sem coordenadas no cadastro de origem na geração desta OS. @endif
Destino planejado
@if($ordem->destino_latitude_planejada !== null && $ordem->destino_longitude_planejada !== null) {{ number_format($ordem->destino_latitude_planejada,7,'.','') }}, {{ number_format($ordem->destino_longitude_planejada,7,'.','') }} @else Sem coordenadas no cadastro de destino na geração desta OS. @endif
Trecho vazio até a origem
Posição do caminhão no início da viagem → chegada na origem.
Km vazios até origem: {{ $ordem->km_vazio_ate_origem !== null ? number_format($ordem->km_vazio_ate_origem,3,',','.') . ' km' : '—' }}
Trecho carregado
Saída da origem → chegada no destino. As leituras permitem medir os quilômetros produtivos reais.
Km carregados: {{ $ordem->kmCarregado() !== null ? number_format($ordem->kmCarregado(),3,',','.') . ' km' : '—' }}
Trecho vazio após o destino
Saída do destino → ponto de espera.
@if($pontoEsperaSugerido)

Mais próximo geograficamente do destino: {{ $pontoEsperaSugerido['ponto']->nome }} ({{ number_format($pontoEsperaSugerido['distancia_geodesica_km'],2,',','.') }} km em linha geodésica). Não representa km rodado em estrada.

@endif
Km vazios após destino: {{ $ordem->km_vazio_pos_destino !== null ? number_format($ordem->km_vazio_pos_destino,3,',','.') . ' km' : '—' }}
Vazio até origem
{{ $ordem->km_vazio_ate_origem !== null ? number_format($ordem->km_vazio_ate_origem,3,',','.') . ' km' : '—' }}
Km carregados
{{ $ordem->kmCarregado() !== null ? number_format($ordem->kmCarregado(),3,',','.') . ' km' : '—' }}
Vazio pós-destino
{{ $ordem->km_vazio_pos_destino !== null ? number_format($ordem->km_vazio_pos_destino,3,',','.') . ' km' : '—' }}
Km operação consolidada
{{ $ordem->kmOperacaoConsolidado() !== null ? number_format($ordem->kmOperacaoConsolidado(),3,',','.') . ' km' : '—' }}
% km produtivo
{{ $ordem->percentualKmCarregado() !== null ? number_format($ordem->percentualKmCarregado(),1,',','.') . '%' : '—' }}
% km vazio
{{ $ordem->percentualKmVazio() !== null ? number_format($ordem->percentualKmVazio(),1,',','.') . '%' : '—' }}

Com a cadeia completa de hodômetro, o Sistema MD calcula os km vazios, os km carregados e os percentuais produtivo/vazio. Os indicadores consolidados só aparecem quando os três trechos estão completos. A52/GPS poderá futuramente fornecer as coordenadas, leituras ou a distância efetivamente percorrida.

{{-- Linha 4: Químico, CTE cliente, NF/CTE MD, Notas --}}
{{-- Linha 5: Status, DADOS RT --}}

Informe o início da viagem para usar o status Em Execução.

O início da viagem coloca a OS em execução automaticamente.

Concluído fica disponível somente após informar a saída do destino.

{{-- Observação + OBS Preço --}}
{{-- Checkboxes --}}
{{-- Obs. de Postergamento (visível apenas se postergado) --}}
{{-- Botões --}}
Cancelar
@php // Prepara a matriz no PHP antes de serializar para JavaScript. // Evita que o parser Blade tente interpretar arrays/arrow functions dentro de @json(...). $composicoesPorCavalo = $composicoes ->groupBy('cavalo_id') ->map(function ($grupo) { return $grupo ->map(function ($c) { return [ 'id' => $c->carreta?->id, 'placa' => $c->carreta?->placa, 'subtipo' => $c->carreta?->subtipo, 'capacidade' => $c->carreta?->capacidade_ton !== null ? (float) $c->carreta->capacidade_ton : null, ]; }) ->filter(fn ($c) => !empty($c['id'])) ->values(); }); @endphp
@endsection