From 71d01c6495b27b6e37c6bbb5ded774ee2caa594e Mon Sep 17 00:00:00 2001 From: Krishnadeva Date: Tue, 24 Oct 2023 15:59:55 +0530 Subject: [PATCH] Implement Get mentors by category endpoint (Admin) #26 --- src/controllers/admin/mentor.controller.ts | 31 +++++++++++++ src/routes/admin/mentor/mentor.route.test.ts | 24 ++++++++++ src/routes/admin/mentor/mentor.route.ts | 2 + src/services/admin/mentor.service.ts | 49 ++++++++++++++++++++ 4 files changed, 106 insertions(+) diff --git a/src/controllers/admin/mentor.controller.ts b/src/controllers/admin/mentor.controller.ts index ca94bad3..8f5fbd5b 100644 --- a/src/controllers/admin/mentor.controller.ts +++ b/src/controllers/admin/mentor.controller.ts @@ -2,6 +2,7 @@ import type { Request, Response } from 'express' import { findAllMentorEmails, getAllMentors, + searchMentorsByCategory, updateMentorStatus } from '../../services/admin/mentor.service' import { ApplicationStatus, ProfileTypes } from '../../enums' @@ -163,3 +164,33 @@ export const searchMentors = async ( throw err } } + +export const getAllMentorsByCategory = async ( + req: Request, + res: Response +): Promise> => { + try { + const user = req.user as Profile + const category: string | undefined = req.query.category as + | string + | undefined + + if (user.type !== ProfileTypes.ADMIN) { + return res.status(403).json({ message: 'Only Admins are allowed' }) + } + + const { statusCode, mentors, message } = await searchMentorsByCategory( + category + ) + return res.status(statusCode).json({ mentors, message }) + } catch (err) { + if (err instanceof Error) { + console.error('Error executing query', err) + return res + .status(500) + .json({ error: 'Internal server error', message: err.message }) + } + + throw err + } +} diff --git a/src/routes/admin/mentor/mentor.route.test.ts b/src/routes/admin/mentor/mentor.route.test.ts index 6afe6c44..8d06406c 100644 --- a/src/routes/admin/mentor/mentor.route.test.ts +++ b/src/routes/admin/mentor/mentor.route.test.ts @@ -7,6 +7,8 @@ import { dataSource } from '../../../configs/dbConfig' import bcrypt from 'bcrypt' import { v4 as uuidv4 } from 'uuid' import { mentorApplicationInfo, mockAdmin, mockMentor } from '../../../../mocks' +import type Category from '../../../entities/category.entity' +import type Mentor from '../../../entities/mentor.entity' const port = Math.floor(Math.random() * (9999 - 3000 + 1)) + 3000 @@ -15,6 +17,7 @@ let mentorAgent: supertest.SuperAgentTest let adminAgent: supertest.SuperAgentTest let mentorId: string let mentorProfileId: string +let category: Category describe('Admin mentor routes', () => { beforeAll(async () => { @@ -56,6 +59,7 @@ describe('Admin mentor routes', () => { mentorId = response.body.mentor.uuid mentorProfileId = response.body.mentor.profile.uuid + category = categoryResponse.body.category }, 5000) it('should update the mentor application state', async () => { @@ -178,6 +182,26 @@ describe('Admin mentor routes', () => { await mentorAgent.get(`/api/admin/mentors/search?q=john`).expect(403) }) + it('should return mentors category starts with Computer and a success message when mentors by category are found', async () => { + const response = await adminAgent + .get(`/api/admin/mentors/category?category=${category.category}`) + .expect(200) + + const mentorDetails = response.body.mentors + + mentorDetails.forEach((mentor: Mentor) => { + expect(mentor).toHaveProperty('profile') + expect(mentor).toHaveProperty('application') + expect(mentor).toHaveProperty('category') + }) + }) + + it('should only allow admins to search mentors by category', async () => { + await mentorAgent + .get(`/api/admin/mentors/category?category=${category.category}`) + .expect(403) + }) + afterAll(async () => { await dataSource.destroy() }) diff --git a/src/routes/admin/mentor/mentor.route.ts b/src/routes/admin/mentor/mentor.route.ts index 6db479b8..926aaeb0 100644 --- a/src/routes/admin/mentor/mentor.route.ts +++ b/src/routes/admin/mentor/mentor.route.ts @@ -2,6 +2,7 @@ import express from 'express' import { requireAuth } from '../../../controllers/auth.controller' import { getAllMentorEmails, + getAllMentorsByCategory, getAllMentorsByStatus, mentorStatusHandler, searchMentors, @@ -19,5 +20,6 @@ mentorRouter.put( updateMentorAvailability ) mentorRouter.get('/search', requireAuth, searchMentors) +mentorRouter.get('/category', requireAuth, getAllMentorsByCategory) export default mentorRouter diff --git a/src/services/admin/mentor.service.ts b/src/services/admin/mentor.service.ts index b826d4a8..c598936f 100644 --- a/src/services/admin/mentor.service.ts +++ b/src/services/admin/mentor.service.ts @@ -109,3 +109,52 @@ export const findAllMentorEmails = async ( throw new Error('Error getting mentors emails') } } + +export const searchMentorsByCategory = async ( + category?: string +): Promise<{ + statusCode: number + mentors?: Mentor[] | null + message: string +}> => { + try { + const mentorRepository = dataSource.getRepository(Mentor) + + const categoryQuery = category ? `${category}%` : '' + + const mentors: Mentor[] = await mentorRepository + .createQueryBuilder('mentor') + .innerJoinAndSelect('mentor.category', 'category') + .leftJoinAndSelect('mentor.profile', 'profile') + .select([ + 'mentor.uuid', + 'category.category', + 'mentor.application', + 'profile.contact_email', + 'profile.first_name', + 'profile.last_name', + 'profile.image_url', + 'profile.linkedin_url' + ]) + .where('category.category ILIKE :name', { + name: categoryQuery + }) + .getMany() + + if (!mentors) { + return { + statusCode: 404, + message: 'Mentors not found' + } + } + + return { + statusCode: 200, + mentors, + message: 'All search Mentors by category found' + } + } catch (err) { + console.error('Error getting mentor', err) + throw new Error('Error getting mentor') + } +}