From 564b433a62ad6b8a4ee23de4b432ae34603594fc Mon Sep 17 00:00:00 2001 From: javier Date: Wed, 17 Jun 2026 15:33:02 +0200 Subject: [PATCH] style: manual UI tweaks (users/companies headers, wider layout, user-view, projects index) User's manual changes: header slots with New-user/New-company actions, wider max-w-7xl containers on /admin/users and /companies, plus tweaks to user-view and projects index views. All views compile. Co-Authored-By: Claude Opus 4.8 (1M context) --- resources/views/admin/users.blade.php | 27 +- .../livewire/company-management.blade.php | 27 +- resources/views/livewire/user-form.blade.php | 2 +- resources/views/livewire/user-view.blade.php | 1058 ++++++++--------- resources/views/projects/index.blade.php | 4 +- routes/web.php | 1 + 6 files changed, 561 insertions(+), 558 deletions(-) diff --git a/resources/views/admin/users.blade.php b/resources/views/admin/users.blade.php index 1e43c8d..a8a3ea8 100644 --- a/resources/views/admin/users.blade.php +++ b/resources/views/admin/users.blade.php @@ -1,25 +1,20 @@ -

- {{ __('Administrator') }} β€” {{ __('Users') }} -

+
+

+ {{ __('Users') }} +

+ + + {{ __('New user') }} + + +
- -
-
+ diff --git a/resources/views/livewire/company-management.blade.php b/resources/views/livewire/company-management.blade.php index 1d7edec..d3eb7dd 100644 --- a/resources/views/livewire/company-management.blade.php +++ b/resources/views/livewire/company-management.blade.php @@ -1,4 +1,11 @@ -
+ +
+

{{ __('Company Management') }}

+

{{ __('Manage the companies that participate in projects') }}

+
+
+ +
@if(session('message'))
@@ -6,16 +13,16 @@
@endif -
-
-

{{ __('Company Management') }}

-

{{ __('Manage the companies that participate in projects') }}

+ -
diff --git a/resources/views/livewire/user-form.blade.php b/resources/views/livewire/user-form.blade.php index 3dd6275..67bd563 100644 --- a/resources/views/livewire/user-form.blade.php +++ b/resources/views/livewire/user-form.blade.php @@ -11,7 +11,7 @@
-
+
@if(session('notify'))
diff --git a/resources/views/livewire/user-view.blade.php b/resources/views/livewire/user-view.blade.php index 86f249a..9c4a680 100644 --- a/resources/views/livewire/user-view.blade.php +++ b/resources/views/livewire/user-view.blade.php @@ -1,552 +1,552 @@
- + - {{-- ── Header del usuario ───────────────────────────────────────────── --}} -
+ {{-- ── Header del usuario ───────────────────────────────────────────── --}} +
- {{-- Izquierda: avatar + datos --}} -
- {{-- Avatar --}} -
- - {{ strtoupper(substr($user->first_name ?: $user->name, 0, 1)) }}{{ strtoupper(substr($user->last_name ?: '', 0, 1)) }} - + {{-- Izquierda: avatar + datos --}} +
+ {{-- Avatar --}} +
+ + {{ strtoupper(substr($user->first_name ?: $user->name, 0, 1)) }}{{ strtoupper(substr($user->last_name ?: '', 0, 1)) }} + +
+ + {{-- Nombre + datos de contacto --}} +
+

+ @if($user->title) {{ $user->title }} @endif + {{ $user->first_name && $user->last_name + ? $user->first_name . ' ' . $user->last_name + : $user->name }} +

+ + {{-- Empresa --}} + @if($user->company) +
+ @if($user->company->logo_path && \Illuminate\Support\Facades\Storage::disk('public')->exists($user->company->logo_path)) + + @else + + @endif + {{ $user->company->apodo ?: $user->company->name }} +
+ @endif + + {{-- Contacto inline --}} +
+ @if($user->email) + + + {{ $user->email }} + + @endif + @if($user->phone) + + + {{ $user->phone }} + + @endif + @if($user->address) + + + {{ $user->address }} + + @endif +
+
- {{-- Nombre + datos de contacto --}} -
-

- @if($user->title) {{ $user->title }} @endif - {{ $user->first_name && $user->last_name - ? $user->first_name . ' ' . $user->last_name - : $user->name }} -

+ {{-- Derecha: estado + validez + botones --}} +
+
+ {{-- Estado --}} + @php + $statusBadge = match($user->status ?? 'active') { + 'active' => ['badge-success', 'Activo'], + 'inactive' => ['badge-ghost', 'Inactivo'], + 'suspended' => ['badge-error', 'Suspendido'], + default => ['badge-ghost', ucfirst($user->status ?? '')], + }; + @endphp + {{ $statusBadge[1] }} + + {{-- Rol principal --}} + @foreach($user->roles->take(1) as $role) + + {{ $role->name }} + + @endforeach +
+ + {{-- Validez --}} + @if($user->valid_from || $user->valid_until) + @php + $now = now(); + $from = $user->valid_from; + $until = $user->valid_until; + $isExpired = $until && $until->lt($now); + $expireSoon = !$isExpired && $until && $until->diffInDays($now) <= 30; + $notStarted = $from && $from->gt($now); + $validColor = $isExpired || $notStarted ? 'text-error' : ($expireSoon ? 'text-warning' : 'text-gray-400'); + @endphp +

+ + @if($from && $until) + {{ $from->format('d/m/Y') }} β†’ {{ $until->format('d/m/Y') }} + @elseif($from) + Desde {{ $from->format('d/m/Y') }} + @else + Hasta {{ $until->format('d/m/Y') }} + @endif + @if($isExpired) (Expirado) + @elseif($notStarted) (No activo aΓΊn) + @elseif($expireSoon) (Expira pronto) + @endif +

+ @endif + + {{-- Botones --}} + +
+
+ + + + {{-- ── Tabs ──────────────────────────────────────────────────────────────── --}} +
+
+ +
+ + + + +
+ + {{-- ════════════════════════════════════════════════════════════════════ + TAB: PERMISOS + ════════════════════════════════════════════════════════════════════ --}} + @if($activeTab === 'permissions') +
+ + {{-- Roles --}} +
+
+

+ + Roles asignados +

+ @if($user->roles->isEmpty()) +

Sin roles asignados.

+ @else +
+ @foreach($user->roles as $role) +
+ + {{ $role->name }} + +
+ @endforeach +
+ @endif +
+
+ + {{-- Validez y estado --}} +
+
+

+ + Validez de acceso +

+
+
+ Estado + {{ $statusBadge[1] }} +
+
+ VΓ‘lido desde + + {{ $user->valid_from ? $user->valid_from->format('d/m/Y') : 'β€” (sin lΓ­mite)' }} + +
+
+ VΓ‘lido hasta + + {{ $user->valid_until ? $user->valid_until->format('d/m/Y') : 'β€” (sin lΓ­mite)' }} + +
+
+ Email verificado + @if($user->email_verified_at) + + + {{ $user->email_verified_at->format('d/m/Y') }} + + @else + + + Pendiente + + @endif +
+
+
+
{{-- Empresa --}} @if($user->company) -
- @if($user->company->logo_path && \Illuminate\Support\Facades\Storage::disk('public')->exists($user->company->logo_path)) - - @else - - @endif - {{ $user->company->apodo ?: $user->company->name }} -
- @endif - - {{-- Contacto inline --}} -
- @if($user->email) - - - {{ $user->email }} - - @endif - @if($user->phone) - - - {{ $user->phone }} - - @endif - @if($user->address) - - - {{ $user->address }} - - @endif -
-
-
- - {{-- Derecha: estado + validez + botones --}} -
-
- {{-- Estado --}} - @php - $statusBadge = match($user->status ?? 'active') { - 'active' => ['badge-success', 'Activo'], - 'inactive' => ['badge-ghost', 'Inactivo'], - 'suspended' => ['badge-error', 'Suspendido'], - default => ['badge-ghost', ucfirst($user->status ?? '')], - }; - @endphp - {{ $statusBadge[1] }} - - {{-- Rol principal --}} - @foreach($user->roles->take(1) as $role) - - {{ $role->name }} - - @endforeach -
- - {{-- Validez --}} - @if($user->valid_from || $user->valid_until) - @php - $now = now(); - $from = $user->valid_from; - $until = $user->valid_until; - $isExpired = $until && $until->lt($now); - $expireSoon = !$isExpired && $until && $until->diffInDays($now) <= 30; - $notStarted = $from && $from->gt($now); - $validColor = $isExpired || $notStarted ? 'text-error' : ($expireSoon ? 'text-warning' : 'text-gray-400'); - @endphp -

- - @if($from && $until) - {{ $from->format('d/m/Y') }} β†’ {{ $until->format('d/m/Y') }} - @elseif($from) - Desde {{ $from->format('d/m/Y') }} - @else - Hasta {{ $until->format('d/m/Y') }} - @endif - @if($isExpired) (Expirado) - @elseif($notStarted) (No activo aΓΊn) - @elseif($expireSoon) (Expira pronto) - @endif -

- @endif - - {{-- Botones --}} - -
-
- - - -{{-- ── Tabs ──────────────────────────────────────────────────────────────── --}} -
-
- -
- - - - -
- - {{-- ════════════════════════════════════════════════════════════════════ - TAB: PERMISOS - ════════════════════════════════════════════════════════════════════ --}} - @if($activeTab === 'permissions') -
- - {{-- Roles --}} -
-
-

- - Roles asignados -

- @if($user->roles->isEmpty()) -

Sin roles asignados.

- @else -
- @foreach($user->roles as $role) -
- - {{ $role->name }} - +
+
+

+ + Empresa +

+
+ @if($user->company->logo_path && \Illuminate\Support\Facades\Storage::disk('public')->exists($user->company->logo_path)) + + @else +
+ +
+ @endif +
+

{{ $user->company->name }}

+ @if($user->company->apodo) +

{{ $user->company->apodo }}

+ @endif + @if($user->company->email) +

{{ $user->company->email }}

+ @endif
- @endforeach -
- @endif -
-
- - {{-- Validez y estado --}} -
-
-

- - Validez de acceso -

-
-
- Estado - {{ $statusBadge[1] }} -
-
- VΓ‘lido desde - - {{ $user->valid_from ? $user->valid_from->format('d/m/Y') : 'β€” (sin lΓ­mite)' }} - -
-
- VΓ‘lido hasta - - {{ $user->valid_until ? $user->valid_until->format('d/m/Y') : 'β€” (sin lΓ­mite)' }} - -
-
- Email verificado - @if($user->email_verified_at) - - - {{ $user->email_verified_at->format('d/m/Y') }} - - @else - - - Pendiente - - @endif -
-
-
-
- - {{-- Empresa --}} - @if($user->company) -
-
-

- - Empresa -

-
- @if($user->company->logo_path && \Illuminate\Support\Facades\Storage::disk('public')->exists($user->company->logo_path)) - - @else -
- + @php + $typeBadge = match($user->company->type) { + 'owner' => ['badge-success', 'Promotor'], + 'constructor' => ['badge-primary', 'Constructor'], + 'subcontractor' => ['badge-secondary','Subcontratista'], + 'consultant' => ['badge-info', 'Consultor'], + 'supplier' => ['badge-warning', 'Proveedor'], + default => ['badge-ghost', 'Otro'], + }; + @endphp + {{ $typeBadge[1] }}
- @endif -
-

{{ $user->company->name }}

- @if($user->company->apodo) -

{{ $user->company->apodo }}

- @endif - @if($user->company->email) -

{{ $user->company->email }}

+
+
+ @endif + +
+ @endif + + {{-- ════════════════════════════════════════════════════════════════════ + TAB: PROYECTOS + ════════════════════════════════════════════════════════════════════ --}} + @if($activeTab === 'projects') +
+ + {{-- Formulario asignar --}} +
+
+

+ + Asignar proyecto +

+ @if($availableProjects->isEmpty()) +

El usuario ya estΓ‘ asignado a todos los proyectos disponibles.

+ @else +
+
+ + + @error('addProjectId')

{{ $message }}

@enderror +
+
+ + +
+ +
@endif
- @php - $typeBadge = match($user->company->type) { - 'owner' => ['badge-success', 'Promotor'], - 'constructor' => ['badge-primary', 'Constructor'], - 'subcontractor' => ['badge-secondary','Subcontratista'], - 'consultant' => ['badge-info', 'Consultor'], - 'supplier' => ['badge-warning', 'Proveedor'], - default => ['badge-ghost', 'Otro'], - }; - @endphp - {{ $typeBadge[1] }}
-
-
- @endif -
- @endif - - {{-- ════════════════════════════════════════════════════════════════════ - TAB: PROYECTOS - ════════════════════════════════════════════════════════════════════ --}} - @if($activeTab === 'projects') -
- - {{-- Formulario asignar --}} -
-
-

- - Asignar proyecto -

- @if($availableProjects->isEmpty()) -

El usuario ya estΓ‘ asignado a todos los proyectos disponibles.

+ {{-- Lista proyectos --}} + @if($user->projects->isEmpty()) +
+
+ +

Sin proyectos asignados.

+
+
@else -
-
- - - @error('addProjectId')

{{ $message }}

@enderror -
-
- - -
- + +
@endif +
-
- - {{-- Lista proyectos --}} - @if($user->projects->isEmpty()) -
-
- -

Sin proyectos asignados.

-
-
- @else -
- - - - - - - - - - - - @foreach($user->projects as $project) - @php - $avg = $project->phases->avg('progress_percent') ?? 0; - $sCfg = match($project->status) { - 'in_progress' => ['badge-primary', 'En progreso'], - 'completed' => ['badge-success', 'Completado'], - 'paused' => ['badge-warning', 'Pausado'], - 'planning' => ['badge-ghost', 'PlanificaciΓ³n'], - default => ['badge-ghost', ucfirst($project->status)], - }; - @endphp - - - - - - - - @endforeach - -
ProyectoRolEstadoProgreso
- - {{ $project->name }} - - @if($project->address) -

{{ $project->address }}

- @endif -
- {{ $project->pivot->role_in_project ?? 'β€”' }} - - {{ $sCfg[1] }} - -
- - {{ round($avg) }}% -
-
- -
-
- @endif - -
- @endif - - {{-- ════════════════════════════════════════════════════════════════════ - TAB: ACTIVIDAD - ════════════════════════════════════════════════════════════════════ --}} - @if($activeTab === 'activity') -
- - {{-- Inspecciones --}} -
-
-

- - Últimas inspecciones -

- @if($recentInspections->isEmpty()) -
- -

Sin inspecciones registradas

-
- @else -
- @foreach($recentInspections as $ins) - @php - $rCfg = match($ins->result ?? '') { - 'pass' => ['badge-success', 'OK'], - 'fail' => ['badge-error', 'Fallo'], - default => ['badge-ghost', 'β€”'], - }; - @endphp -
-
- - {{ $ins->template?->name ?? 'InspecciΓ³n' }} - - {{ $rCfg[1] }} -
-
- - @if($ins->feature?->layer?->phase?->project) - - {{ $ins->feature->layer->phase->project->name }} - @endif - - {{ $ins->created_at->diffForHumans() }} -
-
- @endforeach -
- @endif -
-
- - {{-- Issues reportados --}} -
-
-

- - Issues reportados -

- @if($recentIssues->isEmpty()) -
- -

Sin issues reportados

-
- @else -
- @foreach($recentIssues as $issue) - @php - $pCfg = match($issue->priority ?? 'medium') { - 'critical' => ['badge-error', 'CrΓ­tico'], - 'high' => ['badge-warning', 'Alto'], - 'medium' => ['badge-info', 'Medio'], - default => ['badge-ghost', 'Bajo'], - }; - $stCfg = match($issue->status ?? 'open') { - 'open' => 'text-orange-500', - 'closed' => 'text-green-500', - default => 'text-gray-400', - }; - @endphp -
-
- {{ $issue->title }} - {{ $pCfg[1] }} -
-
- - @if($issue->project) - - {{ $issue->project->name }} - @endif - - - {{ ucfirst($issue->status ?? 'open') }} - -
-
- @endforeach -
- @endif -
-
- -
- @endif - - {{-- ════════════════════════════════════════════════════════════════════ - TAB: NOTAS - ════════════════════════════════════════════════════════════════════ --}} - @if($activeTab === 'notes') -
-
-
-

- - Notas internas -

- @if(!$editingNotes) - - @endif -
- - @if($editingNotes) - -
- - -
- @else - @if($user->notes) -
- {{ $user->notes }} -
- @else -
- -

Sin notas.

- -
- @endif @endif + + {{-- ════════════════════════════════════════════════════════════════════ + TAB: ACTIVIDAD + ════════════════════════════════════════════════════════════════════ --}} + @if($activeTab === 'activity') +
+ + {{-- Inspecciones --}} +
+
+

+ + Últimas inspecciones +

+ @if($recentInspections->isEmpty()) +
+ +

Sin inspecciones registradas

+
+ @else +
+ @foreach($recentInspections as $ins) + @php + $rCfg = match($ins->result ?? '') { + 'pass' => ['badge-success', 'OK'], + 'fail' => ['badge-error', 'Fallo'], + default => ['badge-ghost', 'β€”'], + }; + @endphp +
+
+ + {{ $ins->template?->name ?? 'InspecciΓ³n' }} + + {{ $rCfg[1] }} +
+
+ + @if($ins->feature?->layer?->phase?->project) + + {{ $ins->feature->layer->phase->project->name }} + @endif + + {{ $ins->created_at->diffForHumans() }} +
+
+ @endforeach +
+ @endif +
+
+ + {{-- Issues reportados --}} +
+
+

+ + Issues reportados +

+ @if($recentIssues->isEmpty()) +
+ +

Sin issues reportados

+
+ @else +
+ @foreach($recentIssues as $issue) + @php + $pCfg = match($issue->priority ?? 'medium') { + 'critical' => ['badge-error', 'CrΓ­tico'], + 'high' => ['badge-warning', 'Alto'], + 'medium' => ['badge-info', 'Medio'], + default => ['badge-ghost', 'Bajo'], + }; + $stCfg = match($issue->status ?? 'open') { + 'open' => 'text-orange-500', + 'closed' => 'text-green-500', + default => 'text-gray-400', + }; + @endphp +
+
+ {{ $issue->title }} + {{ $pCfg[1] }} +
+
+ + @if($issue->project) + + {{ $issue->project->name }} + @endif + + + {{ ucfirst($issue->status ?? 'open') }} + +
+
+ @endforeach +
+ @endif +
+
+ +
+ @endif + + {{-- ════════════════════════════════════════════════════════════════════ + TAB: NOTAS + ════════════════════════════════════════════════════════════════════ --}} + @if($activeTab === 'notes') +
+
+
+

+ + Notas internas +

+ @if(!$editingNotes) + + @endif +
+ + @if($editingNotes) + +
+ + +
+ @else + @if($user->notes) +
+ {{ $user->notes }} +
+ @else +
+ +

Sin notas.

+ +
+ @endif + @endif +
+
+ @endif +
- @endif - -
-
diff --git a/resources/views/projects/index.blade.php b/resources/views/projects/index.blade.php index 2879e63..598abad 100644 --- a/resources/views/projects/index.blade.php +++ b/resources/views/projects/index.blade.php @@ -13,7 +13,7 @@
-
+
@if(session('success'))
@@ -21,7 +21,7 @@
@endif -
+
diff --git a/routes/web.php b/routes/web.php index 93260ff..210e321 100644 --- a/routes/web.php +++ b/routes/web.php @@ -95,6 +95,7 @@ Route::middleware(['auth'])->group(function () { 'recentIssues' => $recentIssues, ]); })->name('dashboard'); + Route::get('/reports/dashboard', ReportsDashboard::class)->name('reports.dashboard'); Route::prefix('reports')->name('reports.')->group(function () { Route::get('export/projects', [App\Http\Controllers\Reports\ExportController::class, 'exportProjects'])->name('export.projects');