can('view users'), 403); $this->user = $user->load(['roles', 'company', 'projects.phases']); $this->notes = $user->notes ?? ''; $this->loadAvailableProjects(); $this->loadActivity(); } private function loadAvailableProjects(): void { $assignedIds = $this->user->projects->pluck('id'); $this->availableProjects = Project::whereNotIn('id', $assignedIds) ->orderBy('name')->get(); } private function loadActivity(): void { $this->recentInspections = Inspection::where('user_id', $this->user->id) ->with(['feature.layer.phase.project', 'template']) ->latest()->take(8)->get(); $this->recentIssues = Issue::where('reported_by', $this->user->id) ->with(['feature', 'project']) ->latest()->take(8)->get(); } // ── Tabs ───────────────────────────────────────────────────────────────── public function setTab(string $tab): void { $this->activeTab = $tab; } // ── Projects ────────────────────────────────────────────────────────────── public function assignProject(): void { $this->validate([ 'addProjectId' => 'required|exists:projects,id', 'addProjectRole' => 'nullable|string|max:100', ], [], ['addProjectId' => 'proyecto', 'addProjectRole' => 'rol en proyecto']); $this->user->projects()->attach($this->addProjectId, [ 'role_in_project' => $this->addProjectRole ?: null, ]); $this->user->load('projects.phases'); $this->addProjectId = null; $this->addProjectRole = ''; $this->loadAvailableProjects(); $this->dispatch('notify', 'Proyecto asignado.'); } public function removeProject(int $projectId): void { $this->user->projects()->detach($projectId); $this->user->load('projects.phases'); $this->loadAvailableProjects(); $this->dispatch('notify', 'Proyecto desasignado.'); } // ── Permissions (direct, per user) ───────────────────────────────────────── public function togglePermission(string $name): void { if ($this->user->hasDirectPermission($name)) { $this->user->revokePermissionTo($name); } else { $this->user->givePermissionTo($name); } app(PermissionRegistrar::class)->forgetCachedPermissions(); $this->user->load('roles', 'permissions'); $this->dispatch('notify', 'Permisos del usuario actualizados'); } public function setUserGroup(string $group, bool $enabled): void { foreach (Permission::where('group', $group)->pluck('name') as $name) { if ($enabled) { if (! $this->user->hasPermissionTo($name)) { $this->user->givePermissionTo($name); } } elseif ($this->user->hasDirectPermission($name)) { $this->user->revokePermissionTo($name); } } app(PermissionRegistrar::class)->forgetCachedPermissions(); $this->user->load('roles', 'permissions'); $this->dispatch('notify', $enabled ? 'Permisos del grupo concedidos' : 'Permisos directos del grupo quitados'); } // ── Notes ───────────────────────────────────────────────────────────────── public function saveNotes(): void { $this->validate(['notes' => 'nullable|string']); $this->user->update(['notes' => $this->notes ?: null]); $this->editingNotes = false; $this->dispatch('notify', 'Notas guardadas.'); } public function render() { $order = [ 'Proyectos', 'Fases y progreso', 'Capas y elementos', 'Inspecciones', 'Incidencias', 'Empresas', 'Usuarios', 'Roles', 'Informes', 'Archivos', 'General', ]; $grouped = Permission::orderBy('name')->get() ->groupBy(fn ($perm) => $perm->group ?: 'General') ->sortBy(function ($perms, $section) use ($order) { $i = array_search($section, $order, true); return $i === false ? 999 : $i; }); return view('livewire.user-view', [ 'grouped' => $grouped, 'directPerms' => $this->user->getDirectPermissions()->pluck('name')->toArray(), 'rolePerms' => $this->user->getPermissionsViaRoles()->pluck('name')->toArray(), ]); } }