Files
Leantime/app/Domain/Reports/Templates/partials/projectReportBody.blade.php

109 lines
5.3 KiB
PHP

{{--
Project status report body swapped by the period picker via HTMX.
Expects:
$report: array - ReportEngine::buildReport() output for [$projectId]
$period: \Leantime\Domain\Reports\Models\ReportPeriod
$projectId: int
--}}
@php
$summary = $report['summaries'][$projectId] ?? null;
$stats = $report['stats'];
$deltas = $report['deltas'];
$inFlightMilestones = array_merge($report['milestones']['overdue'], $report['milestones']['inProgress']);
$fmt = fn ($n) => \Illuminate\Support\Number::format((float) $n, maxPrecision: 1);
@endphp
<div id="reportBody">
{{-- Header band: status, progress, timeline --}}
@if ($summary !== null)
<div class="reportHeaderBand">
@include('reports::partials.statusPill', ['status' => $summary->latestStatus, 'date' => $summary->latestStatusDate])
<span>
<strong>{{ round($summary->progress['percent'] ?? 0) }}%</strong> {{ __('label.report_complete') }}
@php $completionState = $summary->progress['estimatedCompletionState'] ?? 'ready'; @endphp
@if ($completionState === 'needs_more_data')
· <a href="{{ BASE_URL }}/tickets/showAll" class="btn btn-primary"><i class="fa fa-thumb-tack"></i> {{ __('label.complete_more_todos') }}</a>
@elseif ($completionState === 'complete')
· <a href="{{ BASE_URL }}/projects/showAll" class="btn btn-primary"><i class="fa fa-suitcase"></i> {{ __('label.project_complete_onto_next') }}</a>
@elseif (!empty($summary->progress['estimatedCompletionDate']) && $summary->progress['estimatedCompletionDate'] !== false)
· {{ __('label.estimated_completion') }} {{ $summary->progress['estimatedCompletionDate'] }}
@endif
</span>
<span class="tw-opacity-70">{{ $period->label() }}</span>
</div>
@endif
@include('reports::partials.statTiles', ['tiles' => [
['label' => __('label.milestones_completed'), 'value' => $stats['completed'], 'delta' => ['value' => $deltas['completedDelta'], 'goodWhenUp' => true, 'vs' => __('label.vs_prior_period_short')]],
['label' => __('label.milestones_in_flight'), 'value' => $stats['inFlight']],
['label' => __('label.milestones_overdue'), 'value' => $stats['overdue'], 'tone' => 'danger'],
['label' => __('label.hours_logged'), 'value' => $fmt($stats['hoursLogged']), 'delta' => ['value' => $deltas['hoursDelta'], 'goodWhenUp' => null, 'vs' => __('label.vs_prior_period_short')]],
]])
@include('reports::partials.needsAttention', ['needsAttention' => $report['needsAttention'], 'showProjects' => false])
<div class="reportSection">
<h5 class="subtitle">{{ __('subtitles.accomplished_this_period') }} <span class="sectionCount">{{ count($report['milestones']['completed']) }}</span></h5>
@include('reports::partials.milestoneList', [
'milestones' => $report['milestones']['completed'],
'mode' => 'completed',
'allowOutcomeEdit' => true,
'effortByMilestone' => $report['effort']['byMilestone'],
'period' => $period,
'emptyText' => __('text.report_no_completed_milestones'),
])
@include('reports::partials.changedThisPeriod', ['slippage' => $report['milestones']['slippage'], 'showProjects' => false])
</div>
<div class="reportSection">
<h5 class="subtitle">{{ __('subtitles.in_flight') }} <span class="sectionCount">{{ count($inFlightMilestones) }}</span></h5>
@include('reports::partials.milestoneList', [
'milestones' => $inFlightMilestones,
'mode' => 'inflight',
'effortByMilestone' => $report['effort']['byMilestone'],
'period' => $period,
'emptyText' => __('text.report_no_inflight_milestones'),
])
</div>
<div class="reportSection">
<h5 class="subtitle">{{ __('subtitles.coming_up') }}</h5>
@if (count($report['milestones']['upcomingByQuarter']) === 0)
<div class="tw-opacity-60 tw-text-sm tw-py-2">{{ __('text.report_no_upcoming_milestones') }}</div>
@else
@foreach ($report['milestones']['upcomingByQuarter'] as $quarterLabel => $quarterMilestones)
<h6 class="tw-font-bold tw-opacity-70 tw-mt-3 tw-mb-1">{{ $quarterLabel }}</h6>
@include('reports::partials.milestoneList', [
'milestones' => $quarterMilestones,
'mode' => 'upcoming',
'period' => $period,
'emptyText' => '',
])
@endforeach
@endif
</div>
<div class="reportSection">
<h5 class="subtitle">{{ __('subtitles.goals_kpis') }}</h5>
@include('reports::partials.goalTable', [
'goals' => $report['goals']['goals'],
'emptyText' => __('text.report_no_goals'),
])
</div>
<div class="reportSection">
<h5 class="subtitle">{{ __('subtitles.status_narrative') }}</h5>
@include('reports::partials.statusNarrative', [
'updatesByProject' => $report['statusUpdates'],
'summaries' => $report['summaries'],
'showProjects' => false,
'emptyText' => __('text.report_no_status_updates'),
])
</div>
</div>