['except' => ''], 'roleFilter' => ['except' => ''], 'statusFilter' => ['except' => ''], 'departmentFilter' => ['except' => ''], 'branchFilter' => ['except' => ''], 'sortField' => ['except' => 'name'], 'sortDirection' => ['except' => 'asc'], 'perPage' => ['except' => 25], 'showInactive' => ['except' => false], ]; public function updatingSearch() { $this->resetPage(); } public function updatingRoleFilter() { $this->resetPage(); } public function updatingStatusFilter() { $this->resetPage(); } public function updatingDepartmentFilter() { $this->resetPage(); } public function updatingBranchFilter() { $this->resetPage(); } public function updatingPerPage() { $this->resetPage(); } public function render() { $query = User::query() ->with(['roles' => function($query) { $query->where('user_roles.is_active', true) ->where(function ($q) { $q->whereNull('user_roles.expires_at') ->orWhere('user_roles.expires_at', '>', now()); }); }]) ->withCount(['roles as active_roles_count' => function($query) { $query->where('user_roles.is_active', true) ->where(function ($q) { $q->whereNull('user_roles.expires_at') ->orWhere('user_roles.expires_at', '>', now()); }); }]) ->when($this->search, function ($q) { $q->where(function ($query) { $query->where('name', 'like', '%' . $this->search . '%') ->orWhere('email', 'like', '%' . $this->search . '%') ->orWhere('employee_id', 'like', '%' . $this->search . '%') ->orWhere('phone', 'like', '%' . $this->search . '%') ->orWhere('national_id', 'like', '%' . $this->search . '%'); }); }) ->when($this->roleFilter, function ($q) { $q->whereHas('roles', function ($query) { $query->where('roles.name', $this->roleFilter) ->where('user_roles.is_active', true) ->where(function ($subQ) { $subQ->whereNull('user_roles.expires_at') ->orWhere('user_roles.expires_at', '>', now()); }); }); }) ->when($this->statusFilter, function ($q) { $q->where('status', $this->statusFilter); }) ->when($this->departmentFilter, function ($q) { $q->where('department', $this->departmentFilter); }) ->when($this->branchFilter, function ($q) { $q->where('branch_code', $this->branchFilter); }) ->when(!$this->showInactive, function ($q) { $q->where('status', '!=', 'inactive'); }) ->orderBy($this->sortField, $this->sortDirection); $users = $query->paginate($this->perPage); $roles = Role::where('is_active', true)->orderBy('display_name')->get(); $departments = User::select('department') ->distinct() ->whereNotNull('department') ->where('department', '!=', '') ->orderBy('department') ->pluck('department'); $branches = User::select('branch_code') ->distinct() ->whereNotNull('branch_code') ->where('branch_code', '!=', '') ->orderBy('branch_code') ->pluck('branch_code'); // Get summary statistics $stats = [ 'total' => User::count(), 'active' => User::where('status', 'active')->count(), 'inactive' => User::where('status', 'inactive')->count(), 'suspended' => User::where('status', 'suspended')->count(), ]; return view('livewire.users.index', compact('users', 'roles', 'departments', 'branches', 'stats')); } public function sortBy($field) { if ($this->sortField === $field) { $this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc'; } else { $this->sortField = $field; $this->sortDirection = 'asc'; } } public function clearFilters() { $this->search = ''; $this->roleFilter = ''; $this->statusFilter = ''; $this->departmentFilter = ''; $this->branchFilter = ''; $this->sortField = 'name'; $this->sortDirection = 'asc'; $this->showInactive = false; $this->resetPage(); } public function toggleShowInactive() { $this->showInactive = !$this->showInactive; $this->resetPage(); } public function selectAllUsers() { if ($this->selectAll) { $this->selectedUsers = []; $this->selectAll = false; } else { $this->selectedUsers = User::pluck('id')->toArray(); $this->selectAll = true; } } public function bulkActivate() { if (empty($this->selectedUsers)) { session()->flash('error', 'No users selected.'); return; } $count = User::whereIn('id', $this->selectedUsers) ->where('id', '!=', auth()->id()) ->update(['status' => 'active']); $this->selectedUsers = []; $this->selectAll = false; session()->flash('success', "Activated {$count} users successfully."); } public function bulkDeactivate() { if (empty($this->selectedUsers)) { session()->flash('error', 'No users selected.'); return; } $count = User::whereIn('id', $this->selectedUsers) ->where('id', '!=', auth()->id()) ->update(['status' => 'inactive']); $this->selectedUsers = []; $this->selectAll = false; session()->flash('success', "Deactivated {$count} users successfully."); } public function deactivateUser($userId) { $user = User::findOrFail($userId); if ($user->id === auth()->id()) { session()->flash('error', 'You cannot deactivate your own account.'); return; } $user->update(['status' => 'inactive']); // Log the action activity() ->performedOn($user) ->causedBy(auth()->user()) ->log('User deactivated'); session()->flash('success', "User '{$user->name}' deactivated successfully."); } public function activateUser($userId) { $user = User::findOrFail($userId); $user->update(['status' => 'active']); // Log the action activity() ->performedOn($user) ->causedBy(auth()->user()) ->log('User activated'); session()->flash('success', "User '{$user->name}' activated successfully."); } public function suspendUser($userId) { $user = User::findOrFail($userId); if ($user->id === auth()->id()) { session()->flash('error', 'You cannot suspend your own account.'); return; } $user->update(['status' => 'suspended']); // Log the action activity() ->performedOn($user) ->causedBy(auth()->user()) ->log('User suspended'); session()->flash('success', "User '{$user->name}' suspended successfully."); } public function deleteUser($userId) { $user = User::findOrFail($userId); if ($user->id === auth()->id()) { session()->flash('error', 'You cannot delete your own account.'); return; } try { // Log before deletion activity() ->performedOn($user) ->causedBy(auth()->user()) ->log('User deleted'); $userName = $user->name; $user->delete(); session()->flash('success', "User '{$userName}' deleted successfully."); } catch (\Exception $e) { session()->flash('error', 'Failed to delete user: ' . $e->getMessage()); } } public function getUserRoles($user) { return $user->roles() ->where('user_roles.is_active', true) ->where(function ($q) { $q->whereNull('user_roles.expires_at') ->orWhere('user_roles.expires_at', '>', now()); }) ->pluck('display_name') ->join(', '); } public function getUserPermissionCount($user) { return $user->getAllPermissions()->count(); } public function hasActiveFilters() { return !empty($this->search) || !empty($this->roleFilter) || !empty($this->statusFilter) || !empty($this->departmentFilter) || !empty($this->branchFilter) || $this->showInactive; } public function getSelectedCount() { return count($this->selectedUsers); } public function exportUsers() { // This would typically export to CSV or Excel $users = User::with(['roles']) ->when($this->search, function ($q) { $q->where(function ($query) { $query->where('name', 'like', '%' . $this->search . '%') ->orWhere('email', 'like', '%' . $this->search . '%') ->orWhere('employee_id', 'like', '%' . $this->search . '%'); }); }) ->get(); session()->flash('success', 'Export initiated for ' . $users->count() . ' users.'); } public function resetFilters() { $this->clearFilters(); } public function getRoleBadgeClass($roleName) { return match($roleName) { 'super_admin' => 'bg-gradient-to-r from-purple-500 to-pink-500 text-white', 'administrator' => 'bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200', 'manager' => 'bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200', 'technician' => 'bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200', 'receptionist' => 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200', 'parts_clerk' => 'bg-amber-100 dark:bg-amber-900 text-amber-800 dark:text-amber-200', 'service_advisor' => 'bg-indigo-100 dark:bg-indigo-900 text-indigo-800 dark:text-indigo-200', 'cashier' => 'bg-pink-100 dark:bg-pink-900 text-pink-800 dark:text-pink-200', 'customer' => 'bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-gray-200', default => 'bg-zinc-100 dark:bg-zinc-700 text-zinc-800 dark:text-zinc-200', }; } public function getStatusBadgeClass($status) { return match($status) { 'active' => 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200', 'inactive' => 'bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-gray-200', 'suspended' => 'bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200', default => 'bg-zinc-100 dark:bg-zinc-700 text-zinc-800 dark:text-zinc-200', }; } }