diff --git a/app/Livewire/AdminUsers.php b/app/Livewire/AdminUsers.php
new file mode 100644
index 0000000..ef3926e
--- /dev/null
+++ b/app/Livewire/AdminUsers.php
@@ -0,0 +1,52 @@
+hasRole('Admin')) {
+ abort(403);
+ }
+ $this->roles = Role::all();
+ $this->loadUsers();
+ }
+
+ public function loadUsers()
+ {
+ $this->users = User::with('roles')->orderBy('name')->get();
+ }
+
+ public function updateRole($userId, $roleName)
+ {
+ $user = Auth::user();
+ if (!$user->hasRole('Admin')) {
+ session()->flash('error', 'Solo administradores.');
+ return;
+ }
+
+ $targetUser = User::findOrFail($userId);
+ if ($targetUser->id === $user->id && $targetUser->hasRole('Admin')) {
+ session()->flash('error', 'No puedes cambiarte el rol a ti mismo.');
+ return;
+ }
+
+ $targetUser->syncRoles([$roleName]);
+ $this->loadUsers();
+ $this->dispatch('notify', 'Rol actualizado.');
+ }
+
+ public function render()
+ {
+ return view('livewire.admin-users');
+ }
+}
\ No newline at end of file
diff --git a/app/Livewire/ProjectUsers.php b/app/Livewire/ProjectUsers.php
new file mode 100644
index 0000000..ab0a0a5
--- /dev/null
+++ b/app/Livewire/ProjectUsers.php
@@ -0,0 +1,81 @@
+project = $project;
+ $this->loadUsers();
+ }
+
+ public function loadUsers()
+ {
+ $this->assignedUsers = $this->project->users()->withPivot('role_in_project')->get();
+ $assignedIds = $this->assignedUsers->pluck('id')->toArray();
+ $this->allUsers = User::whereNotIn('id', $assignedIds)->orderBy('name')->get();
+ }
+
+ public function assignUser()
+ {
+ $user = Auth::user();
+ if (!$user->can('assign users') && !$user->hasRole('Admin')) {
+ session()->flash('error', 'No tienes permisos para asignar usuarios.');
+ return;
+ }
+
+ $this->validate([
+ 'selectedUserId' => 'required|exists:users,id',
+ 'selectedRole' => 'required|in:supervisor,consultant,client,viewer',
+ ]);
+
+ $this->project->users()->attach($this->selectedUserId, [
+ 'role_in_project' => $this->selectedRole
+ ]);
+
+ $this->reset(['selectedUserId', 'selectedRole']);
+ $this->loadUsers();
+ $this->dispatch('notify', 'Usuario asignado al proyecto.');
+ }
+
+ public function removeUser($userId)
+ {
+ $user = Auth::user();
+ if (!$user->can('assign users') && !$user->hasRole('Admin')) {
+ session()->flash('error', 'Sin permisos.');
+ return;
+ }
+
+ $this->project->users()->detach($userId);
+ $this->loadUsers();
+ $this->dispatch('notify', 'Usuario eliminado del proyecto.');
+ }
+
+ public function changeRole($userId, $role)
+ {
+ if (!in_array($role, ['supervisor', 'consultant', 'client', 'viewer'])) return;
+
+ $this->project->users()->updateExistingPivot($userId, [
+ 'role_in_project' => $role
+ ]);
+ $this->loadUsers();
+ $this->dispatch('notify', 'Rol actualizado.');
+ }
+
+ public function render()
+ {
+ return view('livewire.project-users');
+ }
+}
\ No newline at end of file
diff --git a/lang/en.json b/lang/en.json
index 9e85cf4..ef916dc 100644
--- a/lang/en.json
+++ b/lang/en.json
@@ -136,5 +136,14 @@
"Document": "Document",
"Other": "Other",
"Color": "Color",
- "Upload": "Upload"
+ "Upload": "Upload",
+ "Assign": "Assign",
+ "Role": "Role",
+ "Supervisor": "Supervisor",
+ "Consultant": "Consultant",
+ "Client": "Client",
+ "Viewer": "Viewer",
+ "Remove": "Remove",
+ "No users assigned yet": "No users assigned yet",
+ "Select": "Select"
}
diff --git a/lang/es.json b/lang/es.json
index 684e924..0bf93fe 100644
--- a/lang/es.json
+++ b/lang/es.json
@@ -137,5 +137,14 @@
"Document": "Documento",
"Other": "Otro",
"Color": "Color",
- "Upload": "Subir"
+ "Upload": "Subir",
+ "Assign": "Asignar",
+ "Role": "Rol",
+ "Supervisor": "Supervisor",
+ "Consultant": "Consultor",
+ "Client": "Cliente",
+ "Viewer": "Espectador",
+ "Remove": "Eliminar",
+ "No users assigned yet": "Sin usuarios asignados",
+ "Select": "Seleccionar"
}
diff --git a/resources/views/admin/users.blade.php b/resources/views/admin/users.blade.php
new file mode 100644
index 0000000..5d92e06
--- /dev/null
+++ b/resources/views/admin/users.blade.php
@@ -0,0 +1,15 @@
+
+ {{ __('Administrator') }} — {{ __('Users') }}
+
+
| {{ __('Name') }} | +{{ __('Email') }} | +{{ __('Role') }} | +{{ __('Language') }} | +{{ __('Actions') }} | +
|---|---|---|---|---|
| {{ $user->name }} | +{{ $user->email }} | +
+
+ @foreach($user->roles as $role)
+
+ {{ __($role->name) }}
+
+ @endforeach
+
+ |
+ {{ strtoupper($user->locale ?? 'en') }} | ++ @can('assign users') + + @endcan + | +
{{ __('No users assigned yet') }}
+ @endif +