157 lines
7.6 KiB
PHP
157 lines
7.6 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Livewire;
|
||
|
|
|
||
|
|
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||
|
|
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||
|
|
use Rappasoft\LaravelLivewireTables\Views\Filters\SelectFilter;
|
||
|
|
use Illuminate\Database\Eloquent\Builder;
|
||
|
|
use Illuminate\Support\Facades\Auth;
|
||
|
|
use Spatie\Permission\Models\Role;
|
||
|
|
use App\Models\User;
|
||
|
|
|
||
|
|
class UserTable extends DataTableComponent
|
||
|
|
{
|
||
|
|
protected $model = User::class;
|
||
|
|
|
||
|
|
public function configure(): void
|
||
|
|
{
|
||
|
|
$this->setPrimaryKey('id')
|
||
|
|
->setDefaultSort('name', 'asc')
|
||
|
|
->setSortingPillsEnabled(false)
|
||
|
|
->setAdditionalSelects([
|
||
|
|
'users.id as id',
|
||
|
|
'users.email as email',
|
||
|
|
'users.email_verified_at as email_verified_at',
|
||
|
|
'users.status as status',
|
||
|
|
'users.phone as phone',
|
||
|
|
'users.company_id as company_id',
|
||
|
|
'users.created_at as created_at',
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function builder(): Builder
|
||
|
|
{
|
||
|
|
return User::with(['roles', 'company']);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function columns(): array
|
||
|
|
{
|
||
|
|
return [
|
||
|
|
Column::make('Usuario', 'name')
|
||
|
|
->sortable()
|
||
|
|
->searchable()
|
||
|
|
->format(function ($value, $row) {
|
||
|
|
$initial = strtoupper(mb_substr($value, 0, 1));
|
||
|
|
$html = '<div class="flex items-center gap-3">';
|
||
|
|
$html .= '<div class="avatar placeholder shrink-0">
|
||
|
|
<div class="bg-neutral text-neutral-content rounded-full w-8">
|
||
|
|
<span class="text-xs font-semibold">'.$initial.'</span>
|
||
|
|
</div>
|
||
|
|
</div>';
|
||
|
|
$html .= '<div>';
|
||
|
|
$html .= '<p class="font-semibold text-sm leading-tight">'.e($value).'</p>';
|
||
|
|
$html .= '<p class="text-xs text-gray-500">'.e($row->email).'</p>';
|
||
|
|
$html .= '</div></div>';
|
||
|
|
return $html;
|
||
|
|
})
|
||
|
|
->html(),
|
||
|
|
|
||
|
|
Column::make('Empresa')
|
||
|
|
->label(fn ($row) =>
|
||
|
|
$row->company
|
||
|
|
? '<span class="text-sm">'.e($row->company->name).'</span>'
|
||
|
|
: '<span class="text-gray-300 text-sm">—</span>'
|
||
|
|
)
|
||
|
|
->html(),
|
||
|
|
|
||
|
|
Column::make('Rol')
|
||
|
|
->label(function ($row) {
|
||
|
|
if ($row->roles->isEmpty()) {
|
||
|
|
return '<span class="badge badge-sm badge-ghost">Sin rol</span>';
|
||
|
|
}
|
||
|
|
return $row->roles->map(fn ($role) =>
|
||
|
|
'<span class="badge badge-sm '.($role->name === 'Admin' ? 'badge-error' : 'badge-primary').'">'.e($role->name).'</span>'
|
||
|
|
)->implode(' ');
|
||
|
|
})
|
||
|
|
->html(),
|
||
|
|
|
||
|
|
Column::make('Estado', 'status')
|
||
|
|
->sortable()
|
||
|
|
->format(function ($value) {
|
||
|
|
$map = [
|
||
|
|
'active' => ['badge-success', 'Activo'],
|
||
|
|
'inactive' => ['badge-ghost', 'Inactivo'],
|
||
|
|
'suspended' => ['badge-error', 'Suspendido'],
|
||
|
|
];
|
||
|
|
[$cls, $label] = $map[$value ?? 'active'] ?? ['badge-ghost', ucfirst($value ?? '')];
|
||
|
|
return '<span class="badge badge-sm '.$cls.'">'.$label.'</span>';
|
||
|
|
})
|
||
|
|
->html(),
|
||
|
|
|
||
|
|
Column::make('Verificado', 'email_verified_at')
|
||
|
|
->sortable()
|
||
|
|
->format(fn ($value) =>
|
||
|
|
$value
|
||
|
|
? '<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-success" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>'
|
||
|
|
: '<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-warning" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>'
|
||
|
|
)
|
||
|
|
->html(),
|
||
|
|
|
||
|
|
Column::make('Acciones')
|
||
|
|
->label(function ($row) {
|
||
|
|
$ver = route('admin.users.show', $row->id);
|
||
|
|
$editar = route('admin.users.edit', $row->id);
|
||
|
|
$name = addslashes($row->name);
|
||
|
|
$isSelf = $row->id === Auth::id();
|
||
|
|
|
||
|
|
$html = '<div class="flex items-center justify-end gap-1">';
|
||
|
|
$html .= '<a href="'.$ver.'" class="btn btn-xs btn-outline" title="Ver" wire:navigate>
|
||
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg>
|
||
|
|
</a>';
|
||
|
|
$html .= '<a href="'.$editar.'" class="btn btn-xs btn-outline btn-info" title="Editar" wire:navigate>
|
||
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/></svg>
|
||
|
|
</a>';
|
||
|
|
if (! $isSelf) {
|
||
|
|
$html .= '<button wire:click="deleteUser('.$row->id.')"
|
||
|
|
wire:confirm="¿Eliminar a \''.$name.'\'? Se perderán todos sus datos."
|
||
|
|
class="btn btn-xs btn-outline btn-error" title="Eliminar">
|
||
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/></svg>
|
||
|
|
</button>';
|
||
|
|
}
|
||
|
|
$html .= '</div>';
|
||
|
|
return $html;
|
||
|
|
})
|
||
|
|
->html(),
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
public function filters(): array
|
||
|
|
{
|
||
|
|
$roleOptions = [''] + Role::orderBy('name')->pluck('name', 'name')->prepend('Rol: todos', '')->toArray();
|
||
|
|
|
||
|
|
return [
|
||
|
|
SelectFilter::make('Rol')
|
||
|
|
->options($roleOptions)
|
||
|
|
->filter(fn (Builder $query, string $value) =>
|
||
|
|
$query->whereHas('roles', fn ($q) => $q->where('name', $value))
|
||
|
|
),
|
||
|
|
|
||
|
|
SelectFilter::make('Estado', 'status')
|
||
|
|
->options([
|
||
|
|
'' => 'Estado: todos',
|
||
|
|
'active' => 'Activo',
|
||
|
|
'inactive' => 'Inactivo',
|
||
|
|
'suspended' => 'Suspendido',
|
||
|
|
])
|
||
|
|
->filter(fn (Builder $query, string $value) => $query->where('status', $value)),
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
public function deleteUser(int $id): void
|
||
|
|
{
|
||
|
|
if ($id === Auth::id()) return;
|
||
|
|
User::findOrFail($id)->delete();
|
||
|
|
}
|
||
|
|
}
|