feat(home): dashboard ligero renombrado a "Home"

- Sustituye el panel saturado de estadísticas por una vista "Home" centrada en lo
  del usuario: mis proyectos (compacto), mis tareas pendientes, incidencias asignadas
  y notificaciones recientes. Sin inundar de detalle (mejor con muchos proyectos).
- Etiqueta "Dashboard" -> "Home" en el menú y la cabecera.
- Elimina el orderByRaw FIELD() (solo MySQL) del antiguo dashboard.
- ExampleTest: ahora valida la conducta real (la raíz redirige a login).

Suite: 71 passing (0 fallos; resueltas las 2 pre-existentes de SQLite).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-19 17:24:30 +02:00
parent 7d390872c3
commit 7e997bc6aa
4 changed files with 132 additions and 390 deletions
+21 -51
View File
@@ -25,65 +25,35 @@ Route::get('/', function () {
// Grupo de rutas protegidas por autenticación
Route::middleware(['auth'])->group(function () {
// Dashboard principal (vista con estadísticas y lista de proyectos)
// Home: vista ligera (proyectos, tareas e incidencias del usuario + notificaciones)
Route::get('/dashboard', function () {
$user = \Illuminate\Support\Facades\Auth::user();
$projectIds = \App\Models\Project::accessibleBy($user)->pluck('id');
$projects = \App\Models\Project::accessibleBy($user)
->withCount('phases')
->with(['phases' => fn($q) => $q->orderBy('order')])
->latest()->take(6)->get();
->with(['phases' => fn ($q) => $q->select('id', 'project_id', 'progress_percent')])
->orderBy('name')->take(8)->get();
$projectsCount = \App\Models\Project::accessibleBy($user)->count();
$activeProjects = \App\Models\Project::accessibleBy($user)->where('status', 'in_progress')->count();
$totalProjects = \App\Models\Project::accessibleBy($user)->count();
$totalPhases = \App\Models\Phase::whereIn('project_id', $projectIds)->count();
$totalFeatures = \App\Models\Feature::whereHas('layer.phase', fn($q) => $q->whereIn('project_id', $projectIds))->count();
$globalProgress = \App\Models\Phase::whereIn('project_id', $projectIds)->avg('progress_percent') ?? 0;
$myTasks = \App\Models\IssueTask::where('assigned_to', $user->id)
->where('is_done', false)
->with('issue.project')
->orderByRaw('due_date IS NULL, due_date ASC')
->take(8)->get();
$myTasksCount = \App\Models\IssueTask::where('assigned_to', $user->id)->where('is_done', false)->count();
$openIssues = \App\Models\Issue::whereIn('project_id', $projectIds)->where('status', 'open')->count();
$criticalIssues = \App\Models\Issue::whereIn('project_id', $projectIds)->where('status', 'open')->where('priority', 'critical')->count();
$pendingInspections = \App\Models\Inspection::whereIn('project_id', $projectIds)->where('status', 'pending')->count();
$completedInspections = \App\Models\Inspection::whereIn('project_id', $projectIds)->where('status', 'completed')->count();
$rejectedInspections = \App\Models\Inspection::whereIn('project_id', $projectIds)->where('status', 'rejected')->count();
$recentInspections = \App\Models\Inspection::whereIn('project_id', $projectIds)
->with(['template', 'feature', 'project'])
->latest()->take(5)->get();
$recentIssues = \App\Models\Issue::whereIn('project_id', $projectIds)
->with(['feature', 'reporter', 'project'])
->where('status', '!=', 'closed')
->orderByRaw("FIELD(priority,'critical','high','medium','low')")
->take(5)->get();
// Projects with delay (planned_end exceeded and not completed)
$delayedPhases = \App\Models\Phase::whereIn('project_id', $projectIds)
->whereNotNull('planned_end')
->where('planned_end', '<', now())
->where('progress_percent', '<', 100)
$myIssues = \App\Models\Issue::where('assigned_to', $user->id)
->whereIn('status', ['open', 'in_review'])
->with('project')
->count();
->latest()->take(6)->get();
$myIssuesCount = \App\Models\Issue::where('assigned_to', $user->id)->whereIn('status', ['open', 'in_review'])->count();
return view('dashboard', [
'stats' => [
'active_projects' => $activeProjects,
'total_projects' => $totalProjects,
'total_phases' => $totalPhases,
'total_features' => $totalFeatures,
'global_progress' => round($globalProgress),
'open_issues' => $openIssues,
'critical_issues' => $criticalIssues,
'pending_inspections' => $pendingInspections,
'completed_inspections'=> $completedInspections,
'rejected_inspections' => $rejectedInspections,
'delayed_phases' => $delayedPhases,
],
'recentProjects' => $projects,
'recentInspections' => $recentInspections,
'recentIssues' => $recentIssues,
]);
$notifications = $user->notifications()->latest()->take(6)->get();
$unreadCount = $user->unreadNotifications()->count();
return view('dashboard', compact(
'user', 'projects', 'projectsCount', 'myTasks', 'myTasksCount',
'myIssues', 'myIssuesCount', 'notifications', 'unreadCount'
));
})->name('dashboard');
Route::get('/reports/dashboard', ReportsDashboard::class)->name('reports.dashboard');