@php
use App\Enums\Accounts\Cronogramas\CronogramaActivityStatus;
use App\Enums\Accounts\Cronogramas\CronogramaProjectStatus;
/** Rótulo da aba exportada (para o subtítulo institucional). */
$tipoLabel = [
'table' => __('Tabela de Atividades'),
'gantt' => __('Gráfico de Gantt'),
'timeline' => __('Linha do Tempo'),
][$exportType] ?? __('Tabela de Atividades');
$brasaoPath = public_path('pmar/assets/img/brasao-2026.png');
/** Cor da barra/etiqueta conforme estado da atividade. */
$statusColor = static function (string $status, bool $overdue = false): string {
if ($overdue) {
return '#c0392b';
}
return match ($status) {
'completed' => '#1e7e34',
'in_progress' => '#1245A8',
'validation' => '#b8860b',
'planning' => '#0c7c8c',
'suspended' => '#6c757d',
'cancelled' => '#343a40',
default => '#8a939b',
};
};
@endphp
{{ __('Cronograma') }} - {{ $project->name }}
{{-- ============================ TABELA ============================ --}}
@if($exportType === 'table')
@if(empty($tableRows))
{{ __('Nenhuma atividade cadastrada.') }}
@else
| {{ __('Item') }} |
{{ __('Atividades') }} |
{{ __('Predecessora') }} |
{{ __('%') }} |
{{ __('Status') }} |
{{ __('Responsável') }} |
{{ __('Início') }} |
{{ __('Término') }} |
{{ __('Descrição') }} |
{{ __('Observação') }} |
@foreach($tableRows as $row)
| {{ $row['code'] }} |
{{ ! empty($row['parent_id']) ? '↳ ' : '' }}{{ $row['title'] }} |
{{ $row['predecessors'] ?: '-' }} |
{{ (int) $row['completion_percent'] }}% |
{{ $row['is_overdue'] ? __('Atrasado') : $row['status_label'] }}
|
{{ $row['responsible'] }} |
{{ $row['planned_start_date'] ? \Carbon\Carbon::parse($row['planned_start_date'])->format('d/m/Y') : '-' }} |
{{ $row['planned_end_date'] ? \Carbon\Carbon::parse($row['planned_end_date'])->format('d/m/Y') : '-' }} |
{{ $row['description'] }} |
{{ $row['notes'] }} |
@endforeach
@endif
@endif
{{-- ============================ GANTT ============================ --}}
@if($exportType === 'gantt')
@php
$withDates = collect($ganttData)->filter(fn ($g) => ! empty($g['start']) && ! empty($g['end']))->values();
$withoutDates = collect($ganttData)->filter(fn ($g) => empty($g['start']) || empty($g['end']))->values();
$months = [];
if ($withDates->isNotEmpty()) {
$min = $withDates->min(fn ($g) => $g['start']);
$max = $withDates->max(fn ($g) => $g['end']);
$cursor = \Carbon\Carbon::parse($min)->startOfMonth();
$limit = \Carbon\Carbon::parse($max)->startOfMonth();
// Limita a 36 meses para manter o PDF legível.
$guard = 0;
while ($cursor->lte($limit) && $guard < 36) {
$months[] = $cursor->format('Y-m');
$cursor->addMonth();
$guard++;
}
}
@endphp
@if($withDates->isEmpty())
{{ __('Nenhuma atividade com datas definidas para o gráfico de Gantt.') }}
@else
| {{ __('Atividade') }} |
@foreach($months as $m)
{{ \Carbon\Carbon::createFromFormat('Y-m', $m)->translatedFormat('M/y') }} |
@endforeach
@foreach($withDates as $g)
@php
$startM = \Carbon\Carbon::parse($g['start'])->format('Y-m');
$endM = \Carbon\Carbon::parse($g['end'])->format('Y-m');
$color = $statusColor($g['status'], $g['overdue'] ?? false);
@endphp
|
{{ ! empty($g['parent_id']) ? '↳ ' : '' }}{{ $g['code'] }}
{{ \Illuminate\Support\Str::limit($g['title'], 45) }}
({{ (int) $g['progress'] }}%)
|
@foreach($months as $m)
@php $on = ($m >= $startM && $m <= $endM); @endphp
|
@endforeach
@endforeach
@if($withoutDates->isNotEmpty())
{{ __('Atividades sem datas definidas') }}
| {{ __('Código') }} |
{{ __('Atividade') }} |
{{ __('Responsável') }} |
{{ __('Status') }} |
{{ __('Progresso') }} |
@foreach($withoutDates as $g)
| {{ $g['code'] }} |
{{ $g['title'] }} |
{{ $g['responsible'] ?: '-' }} |
{{ CronogramaActivityStatus::tryFrom($g['status'])?->label() ?? $g['status'] }}
|
{{ (int) $g['progress'] }}% |
@endforeach
@endif
@endif
@endif
{{-- ========================= LINHA DO TEMPO ========================= --}}
@if($exportType === 'timeline')
@php
$statusBadge = [
'not_started' => '#8a939b',
'planning' => '#0c7c8c',
'in_progress' => '#1245A8',
'validation' => '#b8860b',
'completed' => '#1e7e34',
'suspended' => '#6c757d',
'cancelled' => '#343a40',
];
$tlRows = collect($tableRows)->sortBy([
fn ($a, $b) => (empty($a['planned_start_date']) ? 1 : 0) <=> (empty($b['planned_start_date']) ? 1 : 0),
fn ($a, $b) => ($a['planned_start_date'] ?? '9999') <=> ($b['planned_start_date'] ?? '9999'),
fn ($a, $b) => ($a['sort_order'] ?? 0) <=> ($b['sort_order'] ?? 0),
]);
$grouped = $tlRows->groupBy(function ($row) {
if (empty($row['planned_start_date'])) {
return 'sem_data';
}
return \Carbon\Carbon::parse($row['planned_start_date'])->format('Y-m');
});
@endphp
@if($tlRows->isEmpty())
{{ __('Nenhuma atividade cadastrada.') }}
@else
@foreach($grouped as $monthKey => $rows)
@if($monthKey === 'sem_data')
{{ __('Sem data') }}
@else
{{ \Carbon\Carbon::createFromFormat('Y-m', $monthKey)->translatedFormat('F \d\e Y') }}
@endif
@foreach($rows as $row)
@php
$dotStatus = $row['is_overdue'] ? 'overdue' : $row['status'];
$color = $statusColor($row['status'], $row['is_overdue']);
$startFmt = $row['planned_start_date'] ? \Carbon\Carbon::parse($row['planned_start_date'])->format('d/m/Y') : null;
$endFmt = $row['planned_end_date'] ? \Carbon\Carbon::parse($row['planned_end_date'])->format('d/m/Y') : null;
@endphp
{{ ! empty($row['parent_id']) ? '↳ ' : '' }}{{ $row['code'] }}
{{ $row['title'] }}
{{ $row['is_overdue'] ? __('Atrasado') : $row['status_label'] }}
@if($startFmt || $endFmt)
{{ __('Período') }}: {{ $startFmt ?? '-' }} - {{ $endFmt ?? '-' }}
@endif
@if($row['responsible'])
| {{ __('Responsável') }}: {{ $row['responsible'] }}
@endif
| {{ __('Progresso') }}: {{ (int) $row['completion_percent'] }}%
@endforeach
@endforeach
@endif
@endif