From d8a20869f11d5e1316d4e29a05e09e230d58b1db Mon Sep 17 00:00:00 2001 From: Sherin Thomas Date: Fri, 14 Nov 2025 16:55:37 +0530 Subject: [PATCH 1/5] Add Pagination to interviews route --- src/controllers/interview.controller.ts | 14 +++++++-- src/services/interview.service.ts | 38 +++++++++++++++++++++---- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/controllers/interview.controller.ts b/src/controllers/interview.controller.ts index b3c3bd8..7ac565e 100644 --- a/src/controllers/interview.controller.ts +++ b/src/controllers/interview.controller.ts @@ -3,14 +3,22 @@ import * as interviewService from "../services/interview.service"; import { ApiError } from "../utils/apiError"; export const getInterviews = async (req: Request, res: Response) => { - const interviews = await interviewService.getInterviews(); + const page = parseInt(req.query.page as string) || 1; + const limit = parseInt(req.query.limit as string) || 10; - res.status(200).json({ + const { interviews, total } = await interviewService.getInterviews(page, limit); + + return res.status(200).json({ success: true, - data: interviews, + data: interviews, + page, + limit, + total, + totalPages: Math.ceil(total / limit), }); }; + export const getInterviewById = async (req: Request, res: Response) => { const interviewId = parseInt(req.params.id); diff --git a/src/services/interview.service.ts b/src/services/interview.service.ts index c63f2fb..011952e 100644 --- a/src/services/interview.service.ts +++ b/src/services/interview.service.ts @@ -1,13 +1,39 @@ import { prisma } from "../db/client" -export const getInterviews = async () => { - return await prisma.interviewExperience.findMany({ - orderBy: { - id: "desc", - }, - }); +export const getInterviews = async (page: number = 1, limit: number = 10) => { + const skip = (page - 1) * limit; + + const [interviews, total] = await Promise.all([ + prisma.interviewExperience.findMany({ + skip, + take: limit, + include: { + member: { + select: { + id: true, + name: true, + profilePhoto: true, + }, + }, + }, + orderBy: { + id: "desc", + }, + }), + + prisma.interviewExperience.count(), + ]); + + const formattedInterview = interviews.map( + ({ isAnonymous, member, memberId, ...rest }) => { + return isAnonymous ? {...rest,isAnonymous} : { ...rest,isAnonymous, member }; + } + ); + + return { interviews : formattedInterview , total }; }; + export const getInterviewById = async (interviewId: number) => { return await prisma.interviewExperience.findUnique({ where: { From ccafec6858563ad5d12bb6dd992b28e571e094d3 Mon Sep 17 00:00:00 2001 From: Sherin Thomas Date: Fri, 14 Nov 2025 16:57:21 +0530 Subject: [PATCH 2/5] typo fix --- src/services/interview.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/interview.service.ts b/src/services/interview.service.ts index 011952e..df0664c 100644 --- a/src/services/interview.service.ts +++ b/src/services/interview.service.ts @@ -24,13 +24,13 @@ export const getInterviews = async (page: number = 1, limit: number = 10) => { prisma.interviewExperience.count(), ]); - const formattedInterview = interviews.map( + const formattedInterviews = interviews.map( ({ isAnonymous, member, memberId, ...rest }) => { return isAnonymous ? {...rest,isAnonymous} : { ...rest,isAnonymous, member }; } ); - return { interviews : formattedInterview , total }; + return { interviews : formattedInterviews , total }; }; From 6b2b63f270798e22747b4dca9fe4061ecffb9db6 Mon Sep 17 00:00:00 2001 From: Sherin Thomas Date: Fri, 14 Nov 2025 17:09:10 +0530 Subject: [PATCH 3/5] Update getInterviews test --- tests/Interview.test.ts | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/tests/Interview.test.ts b/tests/Interview.test.ts index 44c0076..5feca84 100644 --- a/tests/Interview.test.ts +++ b/tests/Interview.test.ts @@ -5,7 +5,12 @@ import { Verdict } from '../src/generated/prisma'; describe('getInterviews', () => { it('should return 200 and all interviews', async () => { - const req: any = {}; + const req: any = { + query: { + page: '1', + limit: '10', + }, + }; const res: any = { status: jest.fn().mockReturnThis(), json: jest.fn(), @@ -19,13 +24,22 @@ describe('getInterviews', () => { verdict: Verdict.Selected, content: 'Great experience', isAnonymous: false, - memberId: 'member123', + member: { + id: 'member123', + name: 'John Doe', + profilePhoto: null, + }, }, ]; + const mockReturn = { + interviews: mockInterviews, + total: 1, + }; + jest .spyOn(interviewService, 'getInterviews') - .mockResolvedValue(mockInterviews); + .mockResolvedValue(mockReturn); await getInterviews(req, res); @@ -33,11 +47,14 @@ describe('getInterviews', () => { expect(res.json).toHaveBeenCalledWith({ success: true, data: mockInterviews, + page: 1, + limit: 10, + total: 1, + totalPages: Math.ceil(1 / 10), }); }); }); - describe('getInterviewById', () => { it('should return 200 and the interview if found', async () => { const req: any = { From 5c711b5f7dd1fc3e7cc45449e6b4fc574db1d401 Mon Sep 17 00:00:00 2001 From: Sherin Thomas Date: Mon, 17 Nov 2025 12:21:07 +0530 Subject: [PATCH 4/5] Add some check for page and limit --- src/controllers/interview.controller.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/controllers/interview.controller.ts b/src/controllers/interview.controller.ts index 7ac565e..56ab5f4 100644 --- a/src/controllers/interview.controller.ts +++ b/src/controllers/interview.controller.ts @@ -6,6 +6,13 @@ export const getInterviews = async (req: Request, res: Response) => { const page = parseInt(req.query.page as string) || 1; const limit = parseInt(req.query.limit as string) || 10; + if(isNaN(page) || page<1){ + throw new ApiError("Page must me greater than or equal to 1",400); + } + if(isNaN(limit) || limit<1 || limit>100){ + throw new ApiError("Limit must me between 1 to 100",400) + } + const { interviews, total } = await interviewService.getInterviews(page, limit); return res.status(200).json({ From b2165f6f8d6ccd4b6dfd08b73a52d3b7f026eefb Mon Sep 17 00:00:00 2001 From: Sherin Thomas Date: Mon, 17 Nov 2025 12:34:46 +0530 Subject: [PATCH 5/5] Fix some typos --- src/controllers/interview.controller.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/interview.controller.ts b/src/controllers/interview.controller.ts index 56ab5f4..3b09e6d 100644 --- a/src/controllers/interview.controller.ts +++ b/src/controllers/interview.controller.ts @@ -7,10 +7,10 @@ export const getInterviews = async (req: Request, res: Response) => { const limit = parseInt(req.query.limit as string) || 10; if(isNaN(page) || page<1){ - throw new ApiError("Page must me greater than or equal to 1",400); + throw new ApiError("Page must be greater than or equal to 1",400); } if(isNaN(limit) || limit<1 || limit>100){ - throw new ApiError("Limit must me between 1 to 100",400) + throw new ApiError("Limit must be between 1 to 100",400) } const { interviews, total } = await interviewService.getInterviews(page, limit);