validate([ 'role' => ['nullable', 'in:admin,resident,driver,helper,scanner,store_partner'], 'status' => ['nullable', 'in:active,suspended,pending'], 'verification_status' => ['nullable', 'in:pending,approved,rejected'], 'q' => ['nullable', 'string', 'max:100'], 'per_page' => ['nullable', 'integer', 'min:1', 'max:100'], ]); $perPage = (int) $request->input('per_page', 25); $users = User::query() ->when($request->filled('role'), fn ($q) => $q->where('role', $request->string('role'))) ->when($request->filled('status'), fn ($q) => $q->where('status', $request->string('status'))) ->when($request->filled('q'), function ($q) use ($request) { $term = '%'.$request->string('q').'%'; $q->where(function ($qq) use ($term) { $qq->where('email', 'like', $term) ->orWhere('phone', 'like', $term) ->orWhere('first_name', 'like', $term) ->orWhere('last_name', 'like', $term); }); }) ->when($request->filled('verification_status'), function ($q) use ($request) { $vs = $request->string('verification_status'); $q->where(function ($qq) use ($vs) { $qq->whereHas('driverProfile', fn ($p) => $p->where('verification_status', $vs)) ->orWhereHas('helperProfile', fn ($p) => $p->where('verification_status', $vs)) ->orWhereHas('scannerProfile', fn ($p) => $p->where('verification_status', $vs)) ->orWhereHas('storePartnerProfile', fn ($p) => $p->where('verification_status', $vs)); }); }) ->orderByDesc('id') ->paginate($perPage); $users->load(['residentProfile', 'driverProfile', 'helperProfile', 'scannerProfile', 'storePartnerProfile']); return $this->ok( UserDetailResource::collection($users), null, [ 'page' => $users->currentPage(), 'per_page' => $users->perPage(), 'total' => $users->total(), 'last_page' => $users->lastPage(), ], ); } public function show(User $user): JsonResponse { $user->load(['residentProfile', 'driverProfile', 'helperProfile', 'scannerProfile', 'storePartnerProfile']); return $this->ok(new UserDetailResource($user)); } public function update(UpdateUserRequest $request, User $user): JsonResponse { $user->update($request->validated()); $user->load(['residentProfile', 'driverProfile', 'helperProfile', 'scannerProfile', 'storePartnerProfile']); return $this->ok(new UserDetailResource($user), 'User updated'); } public function suspend(User $user): JsonResponse { if ($user->role === User::ROLE_ADMIN) { return $this->fail('Admin users cannot be suspended via this endpoint', null, 422); } $user->forceFill(['status' => User::STATUS_SUSPENDED])->save(); return $this->ok(new UserDetailResource($user->fresh()), 'User suspended'); } public function activate(User $user): JsonResponse { $user->forceFill(['status' => User::STATUS_ACTIVE])->save(); return $this->ok(new UserDetailResource($user->fresh()), 'User activated'); } public function destroy(User $user): JsonResponse { if ($user->role === User::ROLE_ADMIN) { return $this->fail('Admin users cannot be deleted via this endpoint', null, 422); } $user->delete(); return $this->ok(null, 'User deleted'); } public function approveProfile(Request $request, User $user): JsonResponse { $profile = $user->profile(); if (! $profile || ! method_exists($profile, 'markVerified')) { return $this->fail('User has no verifiable profile', null, 422); } $profile->markVerified($request->user()); $user->forceFill(['status' => User::STATUS_ACTIVE])->save(); return $this->ok(new UserDetailResource($user->fresh()->load($user->profileRelation())), 'Profile approved'); } public function rejectProfile(RejectProfileRequest $request, User $user): JsonResponse { $profile = $user->profile(); if (! $profile || ! method_exists($profile, 'markRejected')) { return $this->fail('User has no verifiable profile', null, 422); } $profile->markRejected($request->user(), $request->validated('reason')); return $this->ok(new UserDetailResource($user->fresh()->load($user->profileRelation())), 'Profile rejected'); } }