In my view of all team members, I like to have two toggling buttons, one for is_admin, and one for is_active.
The is_admin toggling works but when I try to toggle is_active, the is_admin is changed. Why is that?
UPDATE: When I click the circle of the icon it works, but if I click the other part of the icon, the problem appears.
UsersList.php:
<?php
namespace App\Livewire;
use Auth;
use Livewire\Component;
use App\Models\User;
use Livewire\Attributes\On;
use Livewire\Attributes\Url;
use Illuminate\Contracts\View\View;
use Jantinnerezo\LivewireAlert\LivewireAlert;
use Livewire\WithPagination;
class UsersList extends Component
{
use LivewireAlert;
use WithPagination;
public ?User $user = null;
#public Collection $users;
public array $selected = [];
#[Url]
public string $sortColumn = 'users.name'; // Default col to sort
#[Url]
public string $sortDirection = 'asc'; // Default sort order
public array $active;
public array $admin;
public array $searchColumns = [
'name' => '',
'is_admin' => '',
'email' => '',
'is_active' => '',
];
public function toggleIsAdmin(int $userId): void
{
User::where('id', $userId)->update([
'is_admin' => $this->admin[$userId],
]);
}
public function toggleIsActive(int $userId): void
{
User::where('id', $userId)->update([
'is_active' => $this->active[$userId],
]);
}
public function getSelectedCountProperty(): int
{
return count($this->selected);
}
public function deleteConfirm($method, $id = null): void
{
$this->dispatch('swal:confirm', [
'type' => 'warning',
'title' => 'Are you sure?',
'text' => '',
'id' => $id,
'method' => $method,
]);
}
#[On('delete')]
public function delete(int $id): void
{
$pub = User::where('id', $id )->firstOrFail();
$pub->delete();
}
#[On('deleteSelected')]
public function deleteSelected(): void
{
$users = User::whereIn('id', $this->selected)->get();
$users->each->delete();
$this->reset('selected');
}
public function sortByColumn(string $column): void
{
if ($this->sortColumn == $column) {
$this->sortDirection = $this->sortDirection == 'asc' ? 'desc' : 'asc';
} else {
$this->reset('sortDirection');
$this->sortColumn = $column;
}
}
public function render(): View
{
$usersQuery = User::query()
->select(['users.*']);
foreach ($this->searchColumns as $column => $value) {
if (!empty($value)) {
$usersQuery
->when($column === 'name', fn($query) => $query->where('users.' . $column, 'LIKE', '%' . $value . '%'))
->when($column === 'email', fn($query) => $query->where('users.' . $column, 'LIKE', '%' . $value . '%'))
->when($column === 'is_admin', fn($query) => $query->where('users.' . $column, '=', $value-1))
->when($column === 'is_active', fn($query) => $query->where('users.' . $column, '=', $value-1));
}
}
$usersQuery->where('team_id', '=', auth()->user()->team_id);
$usersQuery->orderBy($this->sortColumn, $this->sortDirection);
$users = $usersQuery->get();
$this->admin = $users->mapWithKeys(
fn (User $item) => [$item['id'] => (bool) $item['is_admin']]
)->toArray();
$this->active = $users->mapWithKeys(
fn (User $item) => [$item['id'] => (bool) $item['is_active']]
)->toArray();
return view('livewire.users-list', [
'users' => $usersQuery->paginate(10)
]);
}
}
users-list.blade.php
<div>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Users') }}
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="overflow-hidden bg-white shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<div class="mb-4">
<div class="mb-4">
<a href="{{ route('invitations.index') }}" class="inline-flex items-center px-4 py-2 text-xs font-semibold tracking-widest text-white uppercase bg-gray-800 rounded-md border border-transparent hover:bg-gray-700">
Invites
</a>
</div>
<button type="button"
wire:click="deleteConfirm('deleteSelected')"
wire:loading.attr="disabled"
@disabled(! $this->selectedCount)
class="px-4 py-2 mr-5 text-xs text-red-500 uppercase bg-red-200 rounded-md border border-transparent hover:text-red-700 hover:bg-red-300 disabled:opacity-50 disabled:cursor-not-allowed">
Delete Selected
</button>
</div>
<div class="overflow-hidden overflow-x-auto mb-4 min-w-full align-middle sm:rounded-md">
<table class="min-w-full border divide-y divide-gray-200">
<thead>
<tr>
<th class="px-6 py-3 text-left bg-gray-50">
</th>
<th wire:click="sortByColumn('users.name')" class="px-6 py-3 text-left bg-gray-50">
<span class="text-xs font-medium tracking-wider leading-4 text-gray-500 uppercase">Name</span>
@if ($sortColumn == 'users.name')
@include('svg.sort-' . $sortDirection)
@else
@include('svg.sort')
@endif
</th>
<th wire:click="sortByColumn('users.email')" class="px-6 py-3 text-left bg-gray-50">
<span class="text-xs font-medium tracking-wider leading-4 text-gray-500 uppercase">Email</span>
@if ($sortColumn == 'users.email')
@include('svg.sort-' . $sortDirection)
@else
@include('svg.sort')
@endif
</th>
<th class="px-6 py-3 text-left bg-gray-50">
<span class="text-xs font-medium tracking-wider leading-4 text-gray-500 uppercase">Admin</span>
</th>
<th class="px-6 py-3 text-left bg-gray-50">
<span class="text-xs font-medium tracking-wider leading-4 text-gray-500 uppercase">Active</span>
</th>
</tr>
<tr>
<td></td>
<td class="px-2 py-2">
<input wire:model.live.debounce="searchColumns.name" type="text" placeholder="Search..."
class="w-full text-sm rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" />
</td>
<td class="px-2 py-2">
<input wire:model.live="searchColumns.email" type="text" placeholder="Search..."
class="w-full text-sm rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" />
</td>
<td class="px-2 py-1">
{{-- <select wire:model.live="searchColumns.is_admin"
class="w-full text-sm rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<option value="">choose...</option>
@foreach($is_admins as $id => $is_admin)
<option value="{{ $id }}">{{ $is_admin }}</option>
@endforeach
</select>--}}
</td>
<td class="px-2 py-1">
{{-- <select wire:model.live="searchColumns.is_admin"
class="w-full text-sm rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<option value="">choose...</option>
@foreach($is_admins as $id => $is_admin)
<option value="{{ $id }}">{{ $is_admin }}</option>
@endforeach
</select>--}}
</td>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200 divide-solid">
@foreach($users as $user)
<tr class="bg-white" wire:key="{{ $user->id }}">
<td class="px-4 py-2 text-sm leading-5 text-gray-900 whitespace-no-wrap">
<input type="checkbox" value="{{ $user->id }}" wire:model.live="selected">
</td>
<td class="px-6 py-4 text-sm leading-5 text-gray-900 whitespace-no-wrap">
{{ $user->name }}
</td>
<td class="px-6 py-4 text-sm leading-5 text-gray-900 whitespace-no-wrap">
{{ $user->email }}
</td>
<td class="px-6">
<div class="inline-block relative mr-2 w-10 align-middle transition duration-200 ease-in select-none">
<input wire:model="admin.{{ $user->id }}" wire:click="toggleIsAdmin({{ $user->id }})" type="checkbox" name="toggle" id="{{ $loop->index.$user->id }}" class="block absolute w-6 h-6 bg-white rounded-full border-4 appearance-none cursor-pointer focus:outline-none toggle-checkbox" />
<label for="{{ $loop->index.$user->id }}" class="block overflow-hidden h-6 bg-gray-300 rounded-full cursor-pointer toggle-label"></label>
</div>
</td>
<td class="px-6">
<div class="inline-block relative mr-2 w-10 align-middle transition duration-200 ease-in select-none">
<input wire:model="active.{{ $user->id }}" wire:click="toggleIsActive({{ $user->id }})" type="checkbox" name="toggle2" id="{{ $loop->index.$user->id }}" class="block absolute w-6 h-6 bg-white rounded-full border-4 appearance-none cursor-pointer focus:outline-none toggle-checkbox" />
<label for="{{ $loop->index.$user->id }}" class="block overflow-hidden h-6 bg-gray-300 rounded-full cursor-pointer toggle-label"></label>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
{{ $users->links() }}
</div>
</div>
</div>
</div>
</div>