diff --git a/apps/backend/src/routes/users/route.ts b/apps/backend/src/routes/users/route.ts index 00f7cd5..260afcd 100644 --- a/apps/backend/src/routes/users/route.ts +++ b/apps/backend/src/routes/users/route.ts @@ -1,4 +1,4 @@ -import { and, eq, ilike, isNull, or, sql, not } from "drizzle-orm"; +import { and, eq, ilike, isNull, or, sql, not, inArray } from "drizzle-orm"; import { Hono } from "hono"; import { z } from "zod"; @@ -58,7 +58,7 @@ const usersRoute = new Hono() .optional() .transform((v) => v?.toLowerCase() === "true"), page: z.coerce.number().int().min(0).default(0), - limit: z.coerce.number().int().min(1).max(1000).default(1), + limit: z.coerce.number().int().min(1).max(1000).default(10), q: z.string().default(""), }) ), @@ -70,42 +70,53 @@ const usersRoute = new Hono() ? sql`(SELECT count(*) FROM ${users})` : sql`(SELECT count(*) FROM ${users} WHERE ${users.deletedAt} IS NULL)`; - const result = await db - .select({ - id: users.id, - name: users.name, - email: users.email, - username: users.username, - isEnabled: users.isEnabled, - createdAt: users.createdAt, - updatedAt: users.updatedAt, - ...(includeTrashed ? { deletedAt: users.deletedAt } : {}), - company: respondents.companyName, - role: { - name: rolesSchema.name, - id: rolesSchema.id, - }, - fullCount: totalCountQuery, - }) - .from(users) - .leftJoin(respondents, eq(users.id, respondents.userId)) - .leftJoin(rolesToUsers, eq(users.id, rolesToUsers.userId)) - .leftJoin(rolesSchema, eq(rolesToUsers.roleId, rolesSchema.id)) - .where( - and( - includeTrashed ? undefined : isNull(users.deletedAt), - q - ? or( - ilike(users.name, q), - ilike(users.username, q), - ilike(users.email, q), - eq(users.id, q) - ) - : undefined + // Query to get unique user IDs with pagination (Sub Query) + const userIdsQuery = db + .select({ + id: users.id, + }) + .from(users) + .where( + and( + includeTrashed ? undefined : isNull(users.deletedAt), + q + ? or( + ilike(users.name, q), + ilike(users.username, q), + ilike(users.email, q), + eq(users.id, q) ) + : undefined ) - .offset(page * limit) - .limit(limit); + ) + .offset(page * limit) + .limit(limit); + + // Main query + const result = await db + .select({ + id: users.id, + name: users.name, + email: users.email, + username: users.username, + isEnabled: users.isEnabled, + createdAt: users.createdAt, + updatedAt: users.updatedAt, + ...(includeTrashed ? { deletedAt: users.deletedAt } : {}), + company: respondents.companyName, + role: { + name: rolesSchema.name, + id: rolesSchema.id, + }, + fullCount: totalCountQuery, + }) + .from(users) + .leftJoin(respondents, eq(users.id, respondents.userId)) + .leftJoin(rolesToUsers, eq(users.id, rolesToUsers.userId)) + .leftJoin(rolesSchema, eq(rolesToUsers.roleId, rolesSchema.id)) + .where(inArray(users.id, userIdsQuery)) // using ID from subquery + .orderBy(users.createdAt); // sort by createdAt + // Group roles for each user to prevent duplication const userMap = new Map