@extends('layouts.app') @section('titulo','Plan Anual') @section('contenido')

Plan Anual de Mantenimiento {{ $anio }}

{{-- ===== KPIs ===== --}}
Total OT planificadas
{{ number_format($kpis['total_ots']) }}
Ejecutadas
{{ $kpis['ejecutadas'] }}
{{ $kpis['cumplimiento_pct'] }}% cumplimiento
Pendientes
{{ $kpis['pendientes'] }}
Vencidas
{{ $kpis['vencidas'] }}
Costo estimado
{{ ($appConfig['moneda_simbolo'] ?? 'S/') }} {{ number_format($kpis['costo_total_estimado'],0) }}
Real: {{ number_format($kpis['costo_total_real'],0) }}
Equipos cubiertos
{{ $kpis['equipos_cubiertos'] }}
{{ $kpis['planes_activos'] }} planes activos
{{-- ===== Gráfico distribución + Top 10 ===== --}}
Distribución por frecuencia
@foreach($frecuencias as $f) @endforeach
FrecuenciaDíasOTCosto
{{ $f['nombre'] }} {{ $f['codigo'] }} {{ $f['dias'] ?? '—' }} {{ $f['count'] }} {{ ($appConfig['moneda_simbolo'] ?? 'S/') }} {{ number_format($f['costo'],2) }}
Top 10 equipos más mantenidos
@forelse($top_equipos as $i => $r) @empty @endforelse
#CódigoEquipoÁrea OTEjec.Costo total
{{ $i + 1 }} {{ optional($r['equipo'])->codigo }} {{ optional($r['equipo'])->nombre }} {{ optional($r['area'])->nombre }} {{ $r['count'] }} {{ $r['ejecutadas'] }} {{ ($appConfig['moneda_simbolo'] ?? 'S/') }} {{ number_format($r['costo'],2) }}
Sin OTs para este año.
{{-- ===== Calendario visual del año (12 mini-meses) ===== --}}
Calendario visual del año {{ $anio }} Intensidad de color = cantidad de OT del día
@foreach($meses as $m)
{{ ucfirst($m['nombre']) }}
@php // Calcular offset hasta el primer día (Lunes=1, Domingo=0 en Carbon) $offset = $m['primer_dow'] === 0 ? 6 : $m['primer_dow'] - 1; $cells = []; for ($i = 0; $i < $offset; $i++) $cells[] = null; foreach ($m['dias'] as $d) $cells[] = $d; @endphp @for($i = 0; $i < count($cells); $i++) @if($i % 7 == 0) @endif @if($cells[$i] === null) @else @php $d = $cells[$i]; $clase = $d['count'] > 0 ? 'd con-ot ' . ($d['count'] >= 5 ? 'high' : ($d['count'] >= 2 ? 'med' : 'low')) : 'd'; @endphp @endif @if(($i + 1) % 7 == 0) @endif @endfor
LMMJVSD
 {{ $d['dia'] }}
@endforeach
{{-- ===== Carga mensual por área ===== --}}
Carga mensual por área Conteo de OTs por área cada mes
@foreach(['Ene','Feb','Mar','Abr','May','Jun','Jul','Ago','Sep','Oct','Nov','Dic'] as $mn) @endforeach @forelse($carga_areas as $fila) @for($m = 1; $m <= 12; $m++) @php $v = $fila['meses'][$m]['count'] ?? 0; @endphp @endfor @empty @endforelse @php $tCount = 0; $tCosto = 0; @endphp @for($m = 1; $m <= 12; $m++) @php $tCount += $totales_mes[$m]['count']; $tCosto += $totales_mes[$m]['costo']; @endphp @endfor
Área Meses Total Costo
{{ $mn }}
{{ optional($fila['area'])->nombre }}{{ $v ?: '—' }}{{ $fila['total'] }} {{ ($appConfig['moneda_simbolo'] ?? 'S/') }} {{ number_format($fila['costo'], 0) }}
Sin datos para este año.
TOTAL{{ $totales_mes[$m]['count'] }}{{ $tCount }} {{ ($appConfig['moneda_simbolo'] ?? 'S/') }} {{ number_format($tCosto, 0) }}
{{-- ===== Cronograma visual tipo Gantt ===== --}}
Cronograma de mantenimiento (Gantt) — {{ $gantt_equipos->count() }} equipos Quincenal Mensual Semestral Anual
@foreach([['Ene',4],['Feb',4],['Mar',5],['Abr',4],['May',4],['Jun',5],['Jul',4],['Ago',4],['Sep',5],['Oct',4],['Nov',4],['Dic',5]] as $mes) @endforeach @for($s = 1; $s <= 52; $s++) @endfor @php $areaActual = null; @endphp @forelse($gantt_equipos as $eq) @if($areaActual !== optional($eq['area'])->id) @php $areaActual = optional($eq['area'])->id; @endphp @endif @for($s = 1; $s <= 52; $s++) @endfor @empty @endforelse
Equipo{{ $mes[0] }}
{{ $s }}
📁 {{ optional($eq['area'])->nombre ?? '—' }}
{{ optional($eq['equipo'])->codigo }} {{ optional($eq['equipo'])->nombre }} @if(count($eq['semanas'][$s] ?? []) > 0) @foreach($eq['semanas'][$s] as $ot) @php $c = optional($ot->frecuencia)->codigo; $clase = match($c) { 'QUI' => 'qui', 'MEN' => 'men', 'SEM' => 'sem', 'ANU' => 'anu', default => 'otra', }; @endphp @endforeach @endif
Sin OTs en {{ $anio }}.
@push('scripts_inline') const datosFrec = @json($frecuencias->map(fn($f) => ['nombre'=>$f['nombre'].' ('.$f['codigo'].')', 'count'=>$f['count']])); if (datosFrec.length > 0) { new Chart(document.getElementById('chartFrec'), { type: 'doughnut', data: { labels: datosFrec.map(x => x.nombre), datasets: [{ data: datosFrec.map(x => x.count), backgroundColor: ['#90caf9','#42a5f5','#1565C0','#0D47A1','#90A4AE','#FFC107','#FF9800'], }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'bottom', labels: { boxWidth: 12, font: { size: 10 } } } } } }); } @endpush @endsection