refactor(livewire): organizar componentes y vistas por dominio en subnamespaces

- app/Livewire: 34 componentes agrupados en Issues/, Projects/, Phases/,
  Companies/, Users/, Admin/, Inspections/, Layers/, Media/, Common/
  (Client/, Reports/, Forms/, Actions/ ya estaban). Namespaces actualizados.
- resources/views/livewire: vistas sueltas movidas a subcarpetas espejo
  (companies/, users/, phases/, roles/, inspections/, media/, common/);
  render() actualizado.
- Referencias actualizadas sin romper nada: rutas (FQN, nombres de ruta intactos),
  tags <livewire:...>/@livewire() a alias con punto, y use de los tests.
- No tocado: Volt de Breeze (auth/profile/navigation), y el portal cliente
  (user-nav/client-projects) que ya tenía referencias inconsistentes.

Verificado: 69 rutas OK, vistas compilan, suite 69 passing (solo 2 pre-existentes
sqlite). autoload regenerado con --ignore-platform-reqs (PHP 8.2).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-19 16:54:09 +02:00
parent 9c164bb7ef
commit 7d390872c3
68 changed files with 191 additions and 107 deletions
@@ -0,0 +1,115 @@
<div>
<div class="flex items-center justify-between gap-3 mb-4">
<div>
<h3 class="font-bold">{{ __('Phases') }}</h3>
<p class="text-sm text-base-content/60">Fases del proyecto y su progreso</p>
</div>
@can('manage phases')
<button wire:click="openForm()" class="btn btn-primary btn-sm gap-2">
<x-heroicon-o-plus class="w-4 h-4" /> {{ __('Add Phase') }}
</button>
@endcan
</div>
{{-- Tabla Rappasoft de fases --}}
<livewire:phases.phase-table :project-id="$project->id" :key="'phase-table-'.$project->id" />
{{-- ================================================================
MODAL crear / editar fase
================================================================ --}}
@if($showForm)
<div class="fixed inset-0 z-40 bg-black/50" wire:click="closeForm"></div>
<div class="fixed inset-0 z-50 flex items-center justify-center p-4">
<div class="bg-base-100 rounded-box shadow-2xl w-full max-w-2xl max-h-[90vh] overflow-y-auto">
<div class="flex items-center justify-between p-5 border-b border-base-300">
<h3 class="text-lg font-bold">{{ $editingId ? 'Editar fase' : 'Nueva fase' }}</h3>
<button wire:click="closeForm" class="btn btn-sm btn-ghost btn-circle">
<x-heroicon-o-x-mark class="w-4 h-4" />
</button>
</div>
<form wire:submit.prevent="save" class="p-5 space-y-4">
{{-- Nombre --}}
<div class="form-control">
<label class="label"><span class="label-text font-medium">Nombre <span class="text-error">*</span></span></label>
<input type="text" wire:model="name" autofocus
class="input input-bordered w-full @error('name') input-error @enderror"
placeholder="Ej.: Cimentación" />
@error('name')<label class="label"><span class="label-text-alt text-error">{{ $message }}</span></label>@enderror
</div>
{{-- Descripción --}}
<div class="form-control">
<label class="label"><span class="label-text font-medium">Descripción</span></label>
<textarea wire:model="description"
class="textarea textarea-bordered w-full h-20 resize-y"
placeholder="Detalle de la fase..."></textarea>
</div>
{{-- Orden + Color + Progreso --}}
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
<div class="form-control">
<label class="label"><span class="label-text font-medium">Orden <span class="text-error">*</span></span></label>
<input type="number" min="0" wire:model="order"
class="input input-bordered w-full @error('order') input-error @enderror" />
@error('order')<label class="label"><span class="label-text-alt text-error">{{ $message }}</span></label>@enderror
</div>
<div class="form-control">
<label class="label"><span class="label-text font-medium">Color</span></label>
<input type="color" wire:model="color"
class="input input-bordered w-full h-12 p-1 @error('color') input-error @enderror" />
@error('color')<label class="label"><span class="label-text-alt text-error">{{ $message }}</span></label>@enderror
</div>
<div class="form-control">
<label class="label"><span class="label-text font-medium">Progreso (%)</span></label>
<input type="number" min="0" max="100" wire:model="progressPercent"
class="input input-bordered w-full @error('progressPercent') input-error @enderror" />
@error('progressPercent')<label class="label"><span class="label-text-alt text-error">{{ $message }}</span></label>@enderror
</div>
</div>
{{-- Fechas previstas --}}
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div class="form-control">
<label class="label"><span class="label-text font-medium">Inicio previsto</span></label>
<input type="date" wire:model="plannedStart"
class="input input-bordered w-full @error('plannedStart') input-error @enderror" />
@error('plannedStart')<label class="label"><span class="label-text-alt text-error">{{ $message }}</span></label>@enderror
</div>
<div class="form-control">
<label class="label"><span class="label-text font-medium">Fin previsto</span></label>
<input type="date" wire:model="plannedEnd"
class="input input-bordered w-full @error('plannedEnd') input-error @enderror" />
@error('plannedEnd')<label class="label"><span class="label-text-alt text-error">{{ $message }}</span></label>@enderror
</div>
</div>
{{-- Fechas reales --}}
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div class="form-control">
<label class="label"><span class="label-text font-medium">Inicio real</span></label>
<input type="date" wire:model="actualStart"
class="input input-bordered w-full @error('actualStart') input-error @enderror" />
@error('actualStart')<label class="label"><span class="label-text-alt text-error">{{ $message }}</span></label>@enderror
</div>
<div class="form-control">
<label class="label"><span class="label-text font-medium">Fin real</span></label>
<input type="date" wire:model="actualEnd"
class="input input-bordered w-full @error('actualEnd') input-error @enderror" />
@error('actualEnd')<label class="label"><span class="label-text-alt text-error">{{ $message }}</span></label>@enderror
</div>
</div>
<div class="flex items-center justify-end gap-3 pt-2 border-t border-base-300">
<button type="button" wire:click="closeForm" class="btn btn-ghost">Cancelar</button>
<button type="submit" class="btn btn-primary gap-2" wire:loading.attr="disabled" wire:target="save">
<span wire:loading.remove wire:target="save"><x-heroicon-o-check class="w-4 h-4" /></span>
<span wire:loading wire:target="save" class="loading loading-spinner loading-sm"></span>
{{ $editingId ? 'Actualizar fase' : 'Crear fase' }}
</button>
</div>
</form>
</div>
</div>
@endif
</div>
@@ -0,0 +1,60 @@
<div>
@if(session()->has('message'))
<div class="alert alert-success mb-2">{{ session('message') }}</div>
@endif
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title">{{ __('Progress') }}: {{ $phase->name }}</h2>
<p class="text-sm opacity-70">{{ $phase->project->name ?? '' }}</p>
<div class="mt-4">
<div class="w-full bg-gray-200 rounded-full h-4 mb-2">
<div class="bg-primary h-4 rounded-full transition-all duration-500" style="width: {{ $phase->progress_percent }}%"></div>
</div>
<p class="text-lg font-bold text-center">{{ $phase->progress_percent }}%</p>
</div>
<form wire:submit.prevent="updateProgressManual" class="mt-6 space-y-4">
<div class="form-control">
<label class="label">{{ __('Progress updated') }}</label>
<input type="range" min="0" max="100" wire:model.live="progress" class="range range-primary" />
<div class="flex justify-between text-xs px-2">
<span>0%</span><span>25%</span><span>50%</span><span>75%</span><span>100%</span>
</div>
<div class="text-center mt-1 font-bold">{{ $progress }}%</div>
</div>
<div class="form-control">
<label class="label">{{ __('Comment') }} ({{ __('optional') }})</label>
<textarea wire:model="comment" rows="3" class="textarea textarea-bordered" placeholder="{{ __('Comment') }}..."></textarea>
</div>
<button type="submit" class="btn btn-primary w-full">{{ __('Save progress') }}</button>
</form>
@if($phase->progressUpdates->count() > 0)
<div class="mt-6">
<h3 class="font-semibold mb-2">{{ __('History') }}</h3>
<div class="space-y-2">
@foreach($phase->progressUpdates()->latest()->take(10)->get() as $update)
<div class="border rounded p-2 text-sm">
<div class="flex justify-between">
<span class="font-medium">{{ $update->progress_percent }}%</span>
<span class="text-xs opacity-60">{{ $update->created_at->diffForHumans() }}</span>
</div>
@if($update->comment)
<p class="text-xs mt-1">{{ $update->comment }}</p>
@endif
</div>
@endforeach
</div>
</div>
@endif
</div>
</div>
<div class="mt-4">
<a href="{{ url()->previous() }}" class="btn btn-outline btn-sm"> {{ __('Back') }}</a>
</div>
</div>