@extends('layouts.app') @section('title', 'Projects | DYSON LATAM') @section('content') @php /* |-------------------------------------------------------------------------- | DYSON PROJECTS - VIEW LOGIC |-------------------------------------------------------------------------- */ $totalProjects = $projects->count(); $completedProjects = $projects ->filter(function ($project) { $allItems = $project->stages->concat($project->certifications); if ($allItems->contains(fn($item) => $item->status === 'blocked')) { return false; } if ($allItems->contains(fn($item) => $item->status === 'overdue')) { return false; } return $allItems->isNotEmpty() && $allItems->every(fn($item) => $item->status === 'completed'); }) ->count(); $blockedProjects = $projects ->filter(function ($project) { $allItems = $project->stages->concat($project->certifications); return $allItems->contains(fn($item) => $item->status === 'blocked'); }) ->count(); $overdueProjects = $projects ->filter(function ($project) { $allItems = $project->stages->concat($project->certifications); if ($allItems->contains(fn($item) => $item->status === 'blocked')) { return false; } return $allItems->contains(fn($item) => $item->status === 'overdue'); }) ->count(); $inProgressProjects = $projects ->filter(function ($project) { $allItems = $project->stages->concat($project->certifications); if ($allItems->contains(fn($item) => $item->status === 'blocked')) { return false; } if ($allItems->contains(fn($item) => $item->status === 'overdue')) { return false; } if ($allItems->isNotEmpty() && $allItems->every(fn($item) => $item->status === 'completed')) { return false; } return $allItems->contains(fn($item) => $item->status === 'in_progress'); }) ->count(); $countries = $projects->pluck('country')->filter()->unique('id')->sortBy('name'); $categories = $projects->pluck('category')->filter()->unique('id')->sortBy('name'); $globalStatusCounts = [ 'completed' => 0, 'in_progress' => 0, 'pending' => 0, 'blocked' => 0, 'overdue' => 0, ]; $projectProgressValues = []; foreach ($projects as $project) { $progressItems = $project->stages->concat($project->certifications); $progressTotal = $progressItems->count(); $progressCompleted = $progressItems->where('status', 'completed')->count(); $projectProgressValues[] = $progressTotal > 0 ? round(($progressCompleted / $progressTotal) * 100) : 0; } $averageProgress = count($projectProgressValues) > 0 ? round(array_sum($projectProgressValues) / count($projectProgressValues)) : 0; foreach ($projects as $project) { $globalItems = $project->stages->concat($project->certifications); if ($globalItems->contains(fn($item) => $item->status === 'blocked')) { $globalStatus = 'blocked'; } elseif ($globalItems->contains(fn($item) => $item->status === 'overdue')) { $globalStatus = 'overdue'; } elseif ($globalItems->isNotEmpty() && $globalItems->every(fn($item) => $item->status === 'completed')) { $globalStatus = 'completed'; } elseif ($globalItems->contains(fn($item) => $item->status === 'in_progress')) { $globalStatus = 'in_progress'; } else { $globalStatus = 'pending'; } $globalStatusCounts[$globalStatus]++; } $projectProgressValues = []; foreach ($projects as $project) { $progressItems = $project->stages->concat($project->certifications); $progressTotal = $progressItems->count(); $progressCompleted = $progressItems->where('status', 'completed')->count(); $projectProgressValues[] = $progressTotal > 0 ? round(($progressCompleted / $progressTotal) * 100) : 0; } $averageProgress = count($projectProgressValues) > 0 ? round(array_sum($projectProgressValues) / count($projectProgressValues)) : 0; $stageLabels = [ 'sample_arrival' => 'Sample Arrival', 'lab_testing' => 'Lab Testing', 'cert_release' => 'Certificate Release', 'country_homologation' => 'Country Homologation', ]; $statusLabels = [ 'completed' => 'Completed', 'in_progress' => 'In Progress', 'pending' => 'Pending', 'blocked' => 'Blocked', 'overdue' => 'Overdue', 'na' => 'N/A', ]; $statusClasses = [ 'completed' => 'status-green', 'in_progress' => 'status-blue', 'pending' => 'status-slate', 'blocked' => 'status-red', 'overdue' => 'status-red', 'na' => 'status-slate', ]; $countryInitials = [ 'Mexico' => 'MX', 'Brazil' => 'BR', 'Colombia' => 'CO', 'Argentina' => 'AR', 'Chile' => 'CL', 'Peru' => 'PE', 'Ecuador' => 'EC', ]; @endphp
{{-- HEADER --}}

DYSON NPD Projects

New Product Development Tracker
@if (\Illuminate\Support\Facades\Auth::user()?->role !== 'viewer') + NEW PROJECT @endif
{{-- TABS --}}
{{-- KPIs --}}
Total Projects
{{ $totalProjects }}
of total ({{ $totalProjects }})
Certified
{{ $completedProjects }}
of total ({{ $totalProjects }})
In Progress
{{ $inProgressProjects }}
of total ({{ $totalProjects }})
Blocked / Overdue
{{ $blockedProjects + $overdueProjects }}
of total ({{ $totalProjects }})
{{-- OVERVIEW --}}
{{-- OVERVIEW ANALYTICS --}}
{{-- DISTRIBUTION BY STAGE --}}
Distribution by Stage
@foreach ($stageLabels as $stageKey => $stageLabel) @php $applicableProjects = $projects->filter( fn($project) => $project->stages->contains('stage', $stageKey), ); $activeProjects = $applicableProjects->filter( fn($project) => $project->stages ->where('stage', $stageKey) ->whereIn('status', ['completed', 'in_progress']) ->isNotEmpty(), ); $applicableCount = $applicableProjects->count(); $activeCount = $activeProjects->count(); $stageProgress = $applicableCount > 0 ? round(($activeCount / $applicableCount) * 100) : 0; @endphp @if ($applicableCount > 0)
{{ $stageLabel }} {{ $activeCount }}/{{ $applicableCount }}
@endif @endforeach
{{-- GLOBAL STATUS --}}
Global Status
@foreach ($globalStatusCounts as $statusKey => $statusCount) @if ($statusCount > 0) @php $statusClass = $statusClasses[$statusKey] ?? 'status-slate'; $statusLabel = $statusLabels[$statusKey] ?? ucfirst($statusKey); @endphp
{{ $statusLabel }} {{ $statusCount }}
@endif @endforeach {{-- GLOBAL AVERAGE PROGRESS --}}
Global Average Progress
{{ $averageProgress }}%
{{-- PROJECTS WITH ALERTS --}}
Projects with Alerts
@php $alertProjects = $projects->filter(function ($project) { $alertItems = $project->stages->concat($project->certifications); return $alertItems->contains( fn($item) => in_array($item->status, ['blocked', 'overdue'], true), ); }); @endphp @if ($alertProjects->isEmpty())
No active alerts.
@else @foreach ($alertProjects as $project) @php $alertItems = $project->stages->concat($project->certifications); $alertStatus = $alertItems->contains(fn($item) => $item->status === 'blocked') ? 'blocked' : 'overdue'; $alertStatusClass = $statusClasses[$alertStatus] ?? 'status-red'; $alertStatusLabel = $statusLabels[$alertStatus] ?? ucfirst($alertStatus); @endphp
NPD-{{ str_pad($project->id, 3, '0', STR_PAD_LEFT) }}
{{ $project->name }}
{{ $project->country->name ?? '—' }}
{{ $alertStatusLabel }}
@endforeach @endif
{{-- TRACKER --}}
Project Tracker
@foreach ($projects as $project) @php $trackerItems = $project->stages->concat($project->certifications); $trackerHasBlocked = $trackerItems->contains(fn($item) => $item->status === 'blocked'); $trackerHasOverdue = $trackerItems->contains(fn($item) => $item->status === 'overdue'); $trackerHasInProgress = $trackerItems->contains(fn($item) => $item->status === 'in_progress'); $trackerIsCompleted = $trackerItems->isNotEmpty() && $trackerItems->every(fn($item) => $item->status === 'completed'); if ($trackerHasBlocked) { $trackerStatus = 'blocked'; } elseif ($trackerHasOverdue) { $trackerStatus = 'overdue'; } elseif ($trackerIsCompleted) { $trackerStatus = 'completed'; } elseif ($trackerHasInProgress) { $trackerStatus = 'in_progress'; } else { $trackerStatus = 'pending'; } $trackerProgress = $trackerItems->count() > 0 ? round( ($trackerItems->where('status', 'completed')->count() / $trackerItems->count()) * 100, ) : 0; @endphp
NPD-{{ str_pad($project->id, 3, '0', STR_PAD_LEFT) }} · {{ $project->country->name ?? '—' }} · {{ $project->category->name ?? '—' }} @if ($project->comments->count() > 0) 💬 {{ $project->comments->count() }} @endif
{{ $project->name }}
Model: {{ $project->model }} · Launch: {{ $project->launch_date?->format('Y-m-d') ?? '—' }}
@foreach ($project->stages as $stage)
{{ $stageLabels[$stage->stage] ?? $stage->stage }}
@endforeach
@foreach ($project->certifications as $certification)
{{ $certification->certification }}
@endforeach
{{ $trackerProgress }}%
{{ $statusLabels[$trackerStatus] ?? 'Pending' }} @if (\Illuminate\Support\Facades\Auth::user()?->role === 'admin')
@csrf @method('DELETE')
@endif ▼
{{-- LEFT COLUMN --}}
Lifecycle Stages
@foreach ($project->stages as $stage) @if (\Illuminate\Support\Facades\Auth::user()?->role !== 'viewer')
@csrf @method('PATCH')
{{ $stageLabels[$stage->stage] ?? $stage->stage }}
@else
{{ $stageLabels[$stage->stage] ?? $stage->stage }}
{{ $statusLabels[$stage->status] ?? ucfirst(str_replace('_', ' ', $stage->status)) }}
{{ $stage->completed_at?->format('Y-m-d') ?? '—' }}
{{ $stage->notes ?: '—' }}
@endif @endforeach
{{ $project->country->name ?? 'Country' }} Certifications
@foreach ($project->certifications as $certification) @if (\Illuminate\Support\Facades\Auth::user()?->role !== 'viewer')
@csrf @method('PATCH')
{{ $certification->certification }} @if (!$certification->required) OPTIONAL @endif
@if (\Illuminate\Support\Facades\Auth::user()?->role === 'admin' && !$certification->required) @else
@endif
@else
{{ $certification->certification }} @if (!$certification->required) OPTIONAL @endif
{{ [ 'pending' => 'Pending', 'in_progress' => 'In Progress', 'completed' => 'Completed', 'blocked' => 'Blocked', 'overdue' => 'Overdue', 'na' => 'N/A', ][$certification->status] ?? $certification->status }}
{{ $certification->completed_at?->format('Y-m-d') ?? '—' }}
{{ $certification->notes ?: '—' }}
@endif @endforeach
{{-- RIGHT COLUMN --}}
Comments
@forelse ($project->comments as $comment)
{{ $comment->user->name ?? 'System' }} {{ $comment->created_at->format('d M Y H:i') }}
{{ $comment->text }}
@empty
No comments have been registered.
@endforelse
@if (\Illuminate\Support\Facades\Auth::user()?->role !== 'viewer')
@csrf
@endif
@endforeach
{{-- COUNTRY --}}
Projects by Country
@foreach ($countries as $country) @php $countryProjects = $projects->where('country_id', $country->id); $countryCertRules = [ 'Mexico' => [ 'required' => ['NOM'], 'optional' => ['CRT'], ], 'Brazil' => [ 'required' => ['INMETRO'], 'optional' => ['ANATEL'], ], 'Chile' => [ 'required' => ['SEC'], 'optional' => ['SUBTEL'], ], 'Colombia' => [ 'required' => ['Homologation'], 'optional' => [], ], 'Argentina' => [ 'required' => ['Homologation'], 'optional' => [], ], 'Peru' => [ 'required' => ['Homologation'], 'optional' => [], ], 'Ecuador' => [ 'required' => ['Homologation'], 'optional' => [], ], ]; $certRules = $countryCertRules[$country->name] ?? [ 'required' => ['Homologation'], 'optional' => [], ]; $certifiedProjects = $countryProjects ->filter(function ($project) { $items = $project->stages->concat($project->certifications); return $items->isNotEmpty() && $items->every(fn($item) => $item->status === 'completed'); }) ->count(); $countryProgress = $countryProjects->count() > 0 ? round(($certifiedProjects / $countryProjects->count()) * 100) : 0; @endphp
{{ $country->name }}
{{ $countryProjects->count() }}
{{-- COUNTRY CERTIFICATIONS --}}
@foreach ($certRules['required'] as $cert) ✓ {{ $cert }} REQUIRED @endforeach @foreach ($certRules['optional'] as $cert) ○ {{ $cert }} OPTIONAL @endforeach
{{-- COUNTRY PROGRESS --}}
{{ $certifiedProjects }} certified / {{ $countryProjects->count() }} projects
{{-- PROJECTS IN COUNTRY --}} @foreach ($countryProjects as $project) @php $countryItems = $project->stages->concat($project->certifications); $countryTotalItems = $countryItems->count(); $countryCompletedItems = $countryItems->where('status', 'completed')->count(); $countryProjectProgress = $countryTotalItems > 0 ? round(($countryCompletedItems / $countryTotalItems) * 100) : 0; $countryHasBlocked = $countryItems->contains(fn($item) => $item->status === 'blocked'); $countryHasOverdue = $countryItems->contains(fn($item) => $item->status === 'overdue'); $countryHasInProgress = $countryItems->contains( fn($item) => $item->status === 'in_progress', ); if ($countryHasBlocked) { $countryProjectStatus = 'blocked'; } elseif ($countryHasOverdue) { $countryProjectStatus = 'overdue'; } elseif ( $countryItems->isNotEmpty() && $countryItems->every(fn($item) => $item->status === 'completed') ) { $countryProjectStatus = 'completed'; } elseif ($countryHasInProgress) { $countryProjectStatus = 'in_progress'; } else { $countryProjectStatus = 'pending'; } $countryProjectStatusClass = $statusClasses[$countryProjectStatus] ?? 'status-slate'; @endphp
NPD-{{ str_pad($project->id, 3, '0', STR_PAD_LEFT) }} · {{ \Illuminate\Support\Str::limit($project->name, 20) }}
@if ($project->comments->count() > 0) 💬 {{ $project->comments->count() }} @endif {{ $countryProjectProgress }}% {{ $statusLabels[$countryProjectStatus] ?? 'Pending' }}
{{-- PROJECT CERTIFICATIONS --}}
@foreach ($project->certifications as $certification) {{ $certification->certification }} @endforeach
@endforeach
@endforeach
@endsection