search) { $query->where(function ($q) use ($request) { $q->where('name', 'like', "%{$request->search}%") ->orWhere('email', 'like', "%{$request->search}%") ->orWhere('phone', 'like', "%{$request->search}%") ->orWhere('voip_extension', 'like', "%{$request->search}%"); }); } if ($request->role) { $query->role($request->role); } if ($request->team_id) { $query->whereHas('teams', fn($q) => $q->where('teams.id', $request->team_id)); } if ($request->has('is_active')) { $query->where('is_active', filter_var($request->is_active, FILTER_VALIDATE_BOOLEAN)); } $users = $query->orderBy('created_at', 'desc')->paginate($request->per_page ?? 15); return response()->json($users); } public function agents(): JsonResponse { $user = auth()->user(); if ($user?->hasRole('agent')) { return response()->json([$user->load('roles', 'teams')]); } return response()->json( User::role('agent') ->where('is_active', true) ->with('roles', 'teams') ->orderBy('name') ->get() ); } public function store(Request $request): JsonResponse { Gate::authorize('create', User::class); $validated = $request->validate([ 'name' => 'required|string|max:255', 'email' => 'required|email|unique:users', 'password' => ['required', ...PasswordPolicy::rules()], 'phone' => 'nullable|string|max:20', 'voip_extension' => ['nullable', 'string', 'max:20', 'regex:/^[0-9*#]+$/', 'unique:users,voip_extension'], 'role' => 'required|string|exists:roles,name', ]); $user = User::create([ 'name' => $validated['name'], 'email' => $validated['email'], 'password' => Hash::make($validated['password']), 'phone' => $validated['phone'] ?? null, 'voip_extension' => $validated['voip_extension'] ?? null, ]); $user->assignRole($validated['role']); ActivityLogger::log('user_created', "User {$user->email} created"); return response()->json($user->load('roles'), 201); } public function show(User $user): JsonResponse { Gate::authorize('view', $user); return response()->json($user->load('roles.permissions', 'teams')); } public function update(Request $request, User $user): JsonResponse { Gate::authorize('update', $user); $validated = $request->validate([ 'name' => 'sometimes|string|max:255', 'email' => 'sometimes|email|unique:users,email,' . $user->id, 'password' => ['sometimes', ...PasswordPolicy::rules()], 'phone' => 'nullable|string|max:20', 'voip_extension' => ['nullable', 'string', 'max:20', 'regex:/^[0-9*#]+$/', 'unique:users,voip_extension,' . $user->id], 'is_active' => 'sometimes|boolean', ]); if (isset($validated['password'])) { $validated['password'] = Hash::make($validated['password']); } $user->update($validated); if ($request->role) { $user->syncRoles([$request->role]); } ActivityLogger::log('user_updated', "User {$user->email} updated"); return response()->json($user->load('roles', 'teams')); } public function destroy(User $user): JsonResponse { Gate::authorize('delete', $user); $user->delete(); ActivityLogger::log('user_deleted', "User {$user->email} deleted"); return response()->json(['message' => 'کاربر حذف شد']); } public function toggleActive(User $user): JsonResponse { Gate::authorize('update', $user); $user->update(['is_active' => !$user->is_active]); ActivityLogger::log('user_toggled', "User {$user->email} active: {$user->is_active}"); return response()->json($user); } public function assignRole(Request $request, User $user): JsonResponse { Gate::authorize('update', $user); $request->validate(['role' => 'required|string|exists:roles,name']); $user->syncRoles([$request->role]); return response()->json($user->load('roles')); } public function assignTeam(Request $request, User $user): JsonResponse { Gate::authorize('update', $user); $request->validate(['team_ids' => 'required|array', 'team_ids.*' => 'exists:teams,id']); $user->teams()->sync($request->team_ids); return response()->json($user->load('teams')); } }