@extends('reports.pdf.layout') @section('title', $data['meta']['title']) @php $meta = $data['meta']; $kpis = $data['kpis_quarter']; $series = $data['monthly_series']; $ranking = $data['site_ranking'] ?? []; $objectives = $data['objectives'] ?? []; $fmtNum = function ($v, $unit = '') { if ($v === null) return '—'; $s = is_numeric($v) ? number_format((float) $v, 0, ',', ' ') : (string) $v; return trim($s . ' ' . $unit); }; $fmtDelta = function ($v, $unit = '%') { if ($v === null) return null; $sign = $v > 0 ? '+' : ''; return $sign . number_format((float) $v, 1, ',', ' ') . $unit; }; $deltaClass = function ($v, bool $maximize = true) { if ($v === null || $v == 0) return 'delta-flat'; $up = $v > 0; return ($up === $maximize) ? 'delta-up' : 'delta-down'; }; // Multi-axis line chart geometry. Two axes : TCO (left, €) and // dispo + eco (right, %). Single SVG, fixed pixel size — wkhtmltopdf // 0.12.x renders width="100%" SVGs at 0×0. $chartW = 540; $chartH = 200; $padX = 42; $padY = 24; $tcoVals = array_filter(array_map(fn ($r) => $r['tco'], $series), fn ($v) => $v !== null); $rightVals = []; foreach ($series as $r) { if ($r['availability'] !== null) $rightVals[] = $r['availability']; if ($r['eco_score'] !== null) $rightVals[] = $r['eco_score']; } $minL = !empty($tcoVals) ? min($tcoVals) : 0; $maxL = !empty($tcoVals) ? max($tcoVals) : 1; if ($minL === $maxL) { $maxL = $minL + 1; } $minL = max(0, $minL - ($maxL - $minL) * 0.1); $maxL = $maxL + ($maxL - $minL) * 0.1; $minR = 0; $maxR = 100; $count = count($series); $stepX = $count > 1 ? ($chartW - 2 * $padX) / ($count - 1) : 0; $coords = function ($i, $value, $axis) use ($padX, $padY, $stepX, $chartH, $minL, $maxL, $minR, $maxR) { $x = $padX + $i * $stepX; if ($value === null) return null; if ($axis === 'left') { $y = $chartH - $padY - (($value - $minL) / ($maxL - $minL)) * ($chartH - 2 * $padY); } else { $y = $chartH - $padY - (($value - $minR) / ($maxR - $minR)) * ($chartH - 2 * $padY); } return ['x' => $x, 'y' => $y]; }; $seriesDefs = [ ['key' => 'tco', 'label' => 'TCO (€)', 'color' => '#3B82F6', 'axis' => 'left', 'unit' => '€'], ['key' => 'availability', 'label' => 'Disponibilité (%)', 'color' => '#10B981', 'axis' => 'right', 'unit' => '%'], ['key' => 'eco_score', 'label' => 'Score conduite', 'color' => '#8B5CF6', 'axis' => 'right', 'unit' => '/100'], ]; $renderedSeries = []; foreach ($seriesDefs as $def) { $points = []; foreach ($series as $i => $r) { $v = $r[$def['key']] ?? null; $c = $coords($i, $v, $def['axis']); if ($c !== null) { $points[] = $c + ['value' => $v]; } } $renderedSeries[] = $def + ['points' => $points]; } $toneBg = ['success' => '#D1FAE5', 'warning' => '#FEF3C7', 'danger' => '#FEE2E2', 'neutral' => '#F3F4F6']; $toneColor = ['success' => '#065F46', 'warning' => '#92400E', 'danger' => '#991B1B', 'neutral' => '#374151']; @endphp @section('content')
DADYCAR FLEET MANAGER

{{ $meta['title'] }}

Synthèse globale {{ $meta['code'] }} Période : {{ $meta['period']['label'] }} · {{ $meta['site_label'] }} · {{ $meta['total_vehicles'] }} véhicules · Généré le {{ $meta['generated_at']->locale('fr')->isoFormat('D MMMM YYYY') }}

Indicateurs trimestriels vs objectifs

TCO moyen / véh
{{ $fmtNum($kpis['tco_avg']['value']) }}{{ $kpis['tco_avg']['unit'] }}
@if ($kpis['tco_avg']['delta'] !== null)
{{ $fmtDelta($kpis['tco_avg']['delta']) }} · {{ $kpis['tco_avg']['delta_label'] }}
@else
{{ $kpis['tco_avg']['delta_label'] }}
@endif
Disponibilité moy
{{ $fmtNum($kpis['availability']['value']) }}{{ $kpis['availability']['unit'] }}
@if ($kpis['availability']['delta'] !== null)
{{ $fmtDelta($kpis['availability']['delta'], ' pts') }} · {{ $kpis['availability']['delta_label'] }}
@else
{{ $kpis['availability']['delta_label'] }}
@endif
Score conduite moy
{{ $fmtNum($kpis['eco_score']['value']) }}{{ $kpis['eco_score']['unit'] }}
{{ $kpis['eco_score']['delta_label'] }}
Sinistres trimestre
{{ $fmtNum($kpis['claims']['value']) }}
@php $cd = $kpis['claims']['delta']; @endphp @if ($cd !== null && $cd !== 0)
{{ $cd > 0 ? '+' : '' }}{{ $cd }} · {{ $kpis['claims']['delta_label'] }}
@else
{{ $kpis['claims']['delta_label'] }}
@endif

Tendances {{ $meta['period']['label'] }} — Évolution mensuelle

@if (!empty($series)) {{-- baseline --}} {{-- left axis label --}} € {{ number_format($maxL, 0, ',', ' ') }} € {{ number_format($minL, 0, ',', ' ') }} {{-- right axis label --}} {{ $maxR }}% {{ $minR }}% {{-- x labels --}} @foreach ($series as $i => $r) {{ $r['label'] }} @endforeach {{-- one polyline per series --}} @foreach ($renderedSeries as $rs) @if (count($rs['points']) > 1) @endif @foreach ($rs['points'] as $p) @endforeach @endforeach {{-- legend --}} @php $lx = $padX; $ly = 12; @endphp @foreach ($renderedSeries as $rs) {{ $rs['label'] }} @php $lx += 130; @endphp @endforeach @else

Pas de données mensuelles pour la période.

@endif

Classement des sites — Score global

@if (!empty($ranking)) @foreach ($ranking as $r) @php $rTone = $r['tier'] ?? 'neutral'; $rBg = $toneBg[$rTone] ?? $toneBg['neutral']; $rFg = $toneColor[$rTone] ?? $toneColor['neutral']; @endphp @endforeach
# Site Score
#{{ $r['rank'] }} {{ $r['label'] }}
{{ $r['sublabel'] }}
{{ number_format($r['score'], 0, ',', ' ') }}/100
@else

Aucun site avec véhicules sur la période.

@endif

Objectifs vs Réalisé — {{ $meta['period']['label'] }}

@if (!empty($objectives)) @foreach ($objectives as $o) @php $sTone = $o['status']['tone'] ?? 'neutral'; $sBg = $toneBg[$sTone] ?? $toneBg['neutral']; $sFg = $toneColor[$sTone] ?? $toneColor['neutral']; @endphp @endforeach
KPI Objectif Réalisé Écart Statut
{{ $o['kpi'] }} {{ $o['objective'] }} {{ $o['actual'] }} {{ $o['gap'] }} {{ $o['status']['label'] }}
@else

Pas d'objectifs définis.

@endif
@endsection