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:
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Users;
|
||||
|
||||
use Livewire\Component;
|
||||
use Livewire\Attributes\Layout;
|
||||
use App\Models\User;
|
||||
use App\Models\Company;
|
||||
use Spatie\Permission\Models\Role;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Validation\Rules\Password;
|
||||
|
||||
#[Layout('layouts.app')]
|
||||
class UserForm extends Component
|
||||
{
|
||||
public ?User $user = null;
|
||||
|
||||
// Información personal
|
||||
public string $title = '';
|
||||
public string $lastName = '';
|
||||
public string $firstName = '';
|
||||
|
||||
// Validación
|
||||
public string $userStatus = 'active';
|
||||
public string $validFrom = '';
|
||||
public string $validUntil = '';
|
||||
public string $formPassword = '';
|
||||
|
||||
// Contacto
|
||||
public ?int $companyId = null;
|
||||
public string $address = '';
|
||||
public string $phone = '';
|
||||
public string $email = '';
|
||||
|
||||
// Permisos
|
||||
public string $formRole = '';
|
||||
|
||||
// Preferencias
|
||||
public string $locale = 'es';
|
||||
|
||||
// Notas
|
||||
public string $notes = '';
|
||||
|
||||
// Catálogos
|
||||
public $roles;
|
||||
public $companies;
|
||||
|
||||
/** Idiomas disponibles (código => nombre + archivo de bandera). */
|
||||
public array $languages = [
|
||||
'es' => ['name' => 'Español', 'flag' => 'es.svg'],
|
||||
'en' => ['name' => 'English', 'flag' => 'gb.svg'],
|
||||
];
|
||||
|
||||
public function mount(?User $user = null): void
|
||||
{
|
||||
abort_unless(Auth::user()->can('create users') || Auth::user()->can('edit users'), 403);
|
||||
|
||||
$this->roles = Role::orderBy('name')->get();
|
||||
$this->companies = Company::where('estado', 'activo')->orderBy('name')->get();
|
||||
$this->formRole = $this->roles->first()?->name ?? '';
|
||||
|
||||
if ($user && $user->exists) {
|
||||
$this->user = $user;
|
||||
$this->title = $user->title ?? '';
|
||||
$this->lastName = $user->last_name ?? '';
|
||||
$this->firstName = $user->first_name ?? '';
|
||||
$this->userStatus = $user->status ?? 'active';
|
||||
$this->validFrom = $user->valid_from?->format('Y-m-d') ?? '';
|
||||
$this->validUntil = $user->valid_until?->format('Y-m-d') ?? '';
|
||||
$this->companyId = $user->company_id;
|
||||
$this->address = $user->address ?? '';
|
||||
$this->phone = $user->phone ?? '';
|
||||
$this->email = $user->email;
|
||||
$this->notes = $user->notes ?? '';
|
||||
$this->formRole = $user->roles->first()?->name ?? $this->formRole;
|
||||
$this->locale = $user->locale ?? $this->locale;
|
||||
}
|
||||
}
|
||||
|
||||
protected function rules(): array
|
||||
{
|
||||
$id = $this->user?->id ?? 'NULL';
|
||||
$rules = [
|
||||
'lastName' => 'required|string|max:100',
|
||||
'firstName' => 'required|string|max:100',
|
||||
'title' => 'nullable|string|max:20',
|
||||
'userStatus' => 'required|in:active,inactive,suspended',
|
||||
'validFrom' => 'nullable|date',
|
||||
'validUntil' => 'nullable|date|after_or_equal:validFrom',
|
||||
'companyId' => 'required|exists:companies,id',
|
||||
'address' => 'nullable|string',
|
||||
'phone' => 'nullable|string|max:30',
|
||||
'email' => "required|email|max:255|unique:users,email,{$id}",
|
||||
'formRole' => 'required|exists:roles,name',
|
||||
'locale' => 'required|in:' . implode(',', array_keys($this->languages)),
|
||||
];
|
||||
|
||||
if (!$this->user) {
|
||||
$rules['formPassword'] = ['required', Password::min(8)->letters()->mixedCase()->numbers()];
|
||||
} elseif ($this->formPassword !== '') {
|
||||
$rules['formPassword'] = [Password::min(8)->letters()->mixedCase()->numbers()];
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
protected $validationAttributes = [
|
||||
'lastName' => 'apellidos',
|
||||
'firstName' => 'nombre',
|
||||
'userStatus' => 'estado',
|
||||
'validFrom' => 'fecha de inicio',
|
||||
'validUntil' => 'fecha de fin',
|
||||
'companyId' => 'empresa',
|
||||
'formPassword'=> 'contraseña',
|
||||
'formRole' => 'rol',
|
||||
'locale' => 'idioma',
|
||||
];
|
||||
|
||||
public function copyCompanyAddress(): void
|
||||
{
|
||||
if (!$this->companyId) return;
|
||||
$company = Company::find($this->companyId);
|
||||
if ($company?->address) {
|
||||
$this->address = $company->address;
|
||||
}
|
||||
}
|
||||
|
||||
public function save(): void
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
if ($this->user && $this->user->id === Auth::id()
|
||||
&& $this->user->hasRole('Admin') && $this->formRole !== 'Admin') {
|
||||
$this->addError('formRole', 'No puedes quitarte el rol Admin a ti mismo.');
|
||||
return;
|
||||
}
|
||||
|
||||
$fullName = trim($this->firstName . ' ' . $this->lastName);
|
||||
|
||||
$data = [
|
||||
'name' => $fullName,
|
||||
'title' => $this->title ?: null,
|
||||
'first_name' => $this->firstName,
|
||||
'last_name' => $this->lastName,
|
||||
'status' => $this->userStatus,
|
||||
'valid_from' => $this->validFrom ?: null,
|
||||
'valid_until'=> $this->validUntil ?: null,
|
||||
'company_id' => $this->companyId,
|
||||
'address' => $this->address ?: null,
|
||||
'phone' => $this->phone ?: null,
|
||||
'email' => $this->email,
|
||||
'notes' => $this->notes ?: null,
|
||||
'locale' => $this->locale,
|
||||
];
|
||||
|
||||
if ($this->formPassword !== '') {
|
||||
$data['password'] = Hash::make($this->formPassword);
|
||||
}
|
||||
|
||||
if ($this->user && $this->user->exists) {
|
||||
$this->user->update($data);
|
||||
$this->user->syncRoles([$this->formRole]);
|
||||
session()->flash('notify', 'Usuario actualizado correctamente.');
|
||||
} else {
|
||||
$user = User::create($data);
|
||||
$user->assignRole($this->formRole);
|
||||
session()->flash('notify', 'Usuario creado correctamente.');
|
||||
}
|
||||
|
||||
$this->redirect(route('admin.users'), navigate: true);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.users.user-form');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user