Skip to content

Commit c53d90f

Browse files
committed
add pagination on user
1 parent 54491a9 commit c53d90f

File tree

4 files changed

+195
-20
lines changed

4 files changed

+195
-20
lines changed

src/api/controllers/user.ts

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
import {Controller, GET, PUT} from 'fastify-decorators';
2-
import {CommonQueryString} from 'schemas';
32

43
import UserService from '../services/user';
54
import authenticate from '../hooks/onRequest/authentication';
6-
import {User} from '../entity/user';
5+
import {User} from '../entity';
76
import {commonQueryString, commonParams} from '../schemas/common';
8-
import {userSchema, userProfileSchema, userLeaderSchema} from '../schemas/user';
7+
import {
8+
userSchema,
9+
userProfileSchema,
10+
userLeaderSchema,
11+
paginatedUserProfileSchema,
12+
} from '../schemas/user';
13+
import {CommonQueryString, PaginatedResponse} from '../../libs/types';
14+
import {paginateResponse} from '../../libs/utils';
915

1016
@Controller({route: '/users'})
1117
export class UserController {
@@ -16,22 +22,21 @@ export class UserController {
1622
options: {
1723
schema: {
1824
querystring: commonQueryString,
19-
response: {200: {type: 'array', items: userProfileSchema}},
25+
response: {200: paginatedUserProfileSchema},
2026
},
2127
onRequest: authenticate,
2228
},
2329
})
2430
async getUserTeachers(
2531
req: AuthenticatedRequest<{Querystring: CommonQueryString}>,
26-
): Promise<User[]> {
27-
const userTeachers = await this.service.getUserTeacher(
32+
): Promise<PaginatedResponse<User>> {
33+
const response = await this.service.getUserTeacherPagination(
2834
req.query.keyword,
2935
'',
3036
req.query.limit,
3137
req.query.skip,
3238
);
33-
34-
return userTeachers;
39+
return paginateResponse(req.query, response);
3540
}
3641

3742
@GET({
@@ -62,22 +67,22 @@ export class UserController {
6267
options: {
6368
schema: {
6469
querystring: commonQueryString,
65-
response: {200: {type: 'array', items: userProfileSchema}},
70+
response: {200: paginatedUserProfileSchema},
6671
},
6772
onRequest: authenticate,
6873
},
6974
})
7075
async getUserStudents(
7176
req: AuthenticatedRequest<{Querystring: CommonQueryString}>,
72-
): Promise<User[]> {
73-
const userTeachers = await this.service.getUserStudent(
77+
): Promise<PaginatedResponse<User>> {
78+
const response = await this.service.getUserStudentPagination(
7479
req.query.keyword,
7580
'',
7681
req.query.limit,
7782
req.query.skip,
7883
);
7984

80-
return userTeachers;
85+
return paginateResponse(req.query, response);
8186
}
8287

8388
@GET({
@@ -132,45 +137,45 @@ export class UserController {
132137
options: {
133138
schema: {
134139
querystring: commonQueryString,
135-
response: {200: {type: 'array', items: userProfileSchema}},
140+
response: {200: paginatedUserProfileSchema},
136141
},
137142
onRequest: authenticate,
138143
},
139144
})
140145
async getUserMentors(
141146
req: AuthenticatedRequest<{Querystring: CommonQueryString}>,
142-
): Promise<User[]> {
143-
const userTeachers = await this.service.getUserMentor(
147+
): Promise<PaginatedResponse<User>> {
148+
const response = await this.service.getUserMentorPagination(
144149
req.query.keyword,
145150
'',
146151
req.query.limit,
147152
req.query.skip,
148153
);
149154

150-
return userTeachers;
155+
return paginateResponse(req.query, response);
151156
}
152157

153158
@GET({
154159
url: '/supporters',
155160
options: {
156161
schema: {
157162
querystring: commonQueryString,
158-
response: {200: {type: 'array', items: userProfileSchema}},
163+
response: {200: paginatedUserProfileSchema},
159164
},
160165
onRequest: authenticate,
161166
},
162167
})
163168
async getUserSupporters(
164169
req: AuthenticatedRequest<{Querystring: CommonQueryString}>,
165-
): Promise<User[]> {
166-
const userTeachers = await this.service.getUserSupporter(
170+
): Promise<PaginatedResponse<User>> {
171+
const response = await this.service.getUserSupporterPagination(
167172
req.query.keyword,
168173
'',
169174
req.query.limit,
170175
req.query.skip,
171176
);
172177

173-
return userTeachers;
178+
return paginateResponse(req.query, response);
174179
}
175180

176181
@GET({

src/api/schemas/user.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import {profileSchema} from './profile';
2+
import {pagination} from './common';
3+
import {eventSchema} from './event';
24

35
const properties = {
46
name: {type: 'string'},
@@ -43,6 +45,17 @@ export const userProfileSchema = {
4345
},
4446
};
4547

48+
export const paginatedUserProfileSchema = {
49+
type: 'object',
50+
properties: {
51+
pages: pagination,
52+
data: {
53+
type: 'array',
54+
items: userProfileSchema,
55+
},
56+
},
57+
};
58+
4659
export const userLeaderSchema = {
4760
type: 'object',
4861
properties: {

src/api/services/user.ts

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,45 @@ export default class UserService {
111111
return users;
112112
}
113113

114+
async getUserTeacherPagination(
115+
name?: string,
116+
schoolId?: string,
117+
limit = 10,
118+
offset = 0,
119+
): Promise<[User[], number]> {
120+
let userQuery = this.repository
121+
.createQueryBuilder('user')
122+
.limit(limit)
123+
.offset(offset * limit)
124+
.orderBy('user.created_at', 'DESC');
125+
126+
if (schoolId) {
127+
userQuery = userQuery.innerJoinAndSelect(
128+
'user.profile',
129+
'profile',
130+
'profile.school_id = :schoolId AND profile.profile_type = :profileType',
131+
{schoolId, profileType: 'teacher'},
132+
);
133+
} else {
134+
userQuery = userQuery.innerJoinAndSelect(
135+
'user.profile',
136+
'profile',
137+
'profile.profile_type = :profileType',
138+
{
139+
profileType: 'teacher',
140+
},
141+
);
142+
}
143+
144+
if (name) {
145+
userQuery = userQuery.where('user.name ILIKE :name', {name: `%${name}%`});
146+
}
147+
148+
const users = await userQuery.getManyAndCount();
149+
150+
return users;
151+
}
152+
114153
async getUserStudent(
115154
name?: string,
116155
schoolId?: string,
@@ -150,6 +189,45 @@ export default class UserService {
150189
return users;
151190
}
152191

192+
async getUserStudentPagination(
193+
name?: string,
194+
schoolId?: string,
195+
limit = 10,
196+
offset = 0,
197+
): Promise<[User[], number]> {
198+
let userQuery = this.repository
199+
.createQueryBuilder('user')
200+
.limit(limit)
201+
.offset(offset * limit)
202+
.orderBy('user.created_at', 'DESC');
203+
204+
if (schoolId) {
205+
userQuery = userQuery.innerJoinAndSelect(
206+
'user.profile',
207+
'profile',
208+
'profile.school_id = :schoolId AND profile.profile_type = :profileType',
209+
{schoolId, profileType: 'student'},
210+
);
211+
} else {
212+
userQuery = userQuery.innerJoinAndSelect(
213+
'user.profile',
214+
'profile',
215+
'profile.profile_type = :profileType',
216+
{
217+
profileType: 'student',
218+
},
219+
);
220+
}
221+
222+
if (name) {
223+
userQuery = userQuery.where('user.name ILIKE :name', {name: `%${name}%`});
224+
}
225+
226+
const users = await userQuery.getManyAndCount();
227+
228+
return users;
229+
}
230+
153231
async getUserStudentNotInTeam(params: NotInTeamParams): Promise<User[]> {
154232
const limit = params?.limit || 10;
155233
const offset = params?.offset || 0;
@@ -233,6 +311,45 @@ export default class UserService {
233311
return users;
234312
}
235313

314+
async getUserMentorPagination(
315+
name?: string,
316+
schoolId?: string,
317+
limit = 10,
318+
offset = 0,
319+
): Promise<[User[], number]> {
320+
let userQuery = this.repository
321+
.createQueryBuilder('user')
322+
.limit(limit)
323+
.offset(offset * limit)
324+
.orderBy('user.created_at', 'DESC');
325+
326+
if (schoolId) {
327+
userQuery = userQuery.innerJoinAndSelect(
328+
'user.profile',
329+
'profile',
330+
'profile.school_id = :schoolId AND profile.profile_type = :profileType',
331+
{schoolId, profileType: 'student'},
332+
);
333+
} else {
334+
userQuery = userQuery.innerJoinAndSelect(
335+
'user.profile',
336+
'profile',
337+
'profile.profile_type = :profileType',
338+
{
339+
profileType: 'mentor',
340+
},
341+
);
342+
}
343+
344+
if (name) {
345+
userQuery = userQuery.where('user.name ILIKE :name', {name: `%${name}%`});
346+
}
347+
348+
const users = await userQuery.getManyAndCount();
349+
350+
return users;
351+
}
352+
236353
async getUserSupporter(
237354
name?: string,
238355
schoolId?: string,
@@ -272,6 +389,45 @@ export default class UserService {
272389
return users;
273390
}
274391

392+
async getUserSupporterPagination(
393+
name?: string,
394+
schoolId?: string,
395+
limit = 10,
396+
offset = 0,
397+
): Promise<[User[], number]> {
398+
let userQuery = this.repository
399+
.createQueryBuilder('user')
400+
.limit(limit)
401+
.offset(offset * limit)
402+
.orderBy('user.created_at', 'DESC');
403+
404+
if (schoolId) {
405+
userQuery = userQuery.innerJoinAndSelect(
406+
'user.profile',
407+
'profile',
408+
'profile.school_id = :schoolId AND profile.profile_type = :profileType',
409+
{schoolId, profileType: 'student'},
410+
);
411+
} else {
412+
userQuery = userQuery.innerJoinAndSelect(
413+
'user.profile',
414+
'profile',
415+
'profile.profile_type = :profileType',
416+
{
417+
profileType: 'supporter',
418+
},
419+
);
420+
}
421+
422+
if (name) {
423+
userQuery = userQuery.where('user.name ILIKE :name', {name: `%${name}%`});
424+
}
425+
426+
const users = await userQuery.getManyAndCount();
427+
428+
return users;
429+
}
430+
275431
async getUserDetail(id: string): Promise<User | undefined> {
276432
return this.repository
277433
.createQueryBuilder('user')

src/libs/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export type CommonQueryString = {
3535
offset: number;
3636
sort?: string;
3737
keyword?: string;
38+
skip?: number;
3839
};
3940

4041
export type QueryString = {

0 commit comments

Comments
 (0)