Skip to content

Commit

Permalink
Admin API for Mentor Details Update
Browse files Browse the repository at this point in the history
  • Loading branch information
Disura-Randunu committed Sep 16, 2024
1 parent d1d6d7a commit a21e647
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 3 deletions.
40 changes: 40 additions & 0 deletions src/controllers/admin/mentor.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,53 @@ import {
findAllMentorEmails,
getAllMentors,
getMentor,
updateMentorDetails,
updateMentorStatus
} from '../../services/admin/mentor.service'
import {
searchMentorsByQuery,
updateAvailability
} from '../../services/mentor.service'
import type { ApiResponse, PaginatedApiResponse } from '../../types'
import { IMG_HOST } from '../../configs/envConfig'

export const updateMentorHandler = async (
req: Request,
res: Response
): Promise<ApiResponse<Mentor>> => {
const user = req.user as Profile

if (user.type !== ProfileTypes.ADMIN) {
return res.status(403).json({ message: 'Only Admins are allowed' })
}

try {
const { mentorId } = req.params
const data = req.body.data ? JSON.parse(req.body.data) : req.body
const mentorUpdateData: Partial<Mentor> = { ...data }
const profileUpdateData: Partial<Profile> = { ...data.profile }

if (req.file) {
profileUpdateData.image_url = `${IMG_HOST}/${req.file.filename}`
}

const { mentor, statusCode, message } = await updateMentorDetails(
mentorId,
mentorUpdateData,
profileUpdateData
)
return res.status(statusCode).json({ mentor, message })
} catch (err) {
if (err instanceof Error) {
console.error('Error updating mentor details:', err)
return res.status(500).json({
error: 'Internal server error',
message: err.message
})
}
throw err
}
}

export const mentorStatusHandler = async (
req: Request,
Expand Down
6 changes: 5 additions & 1 deletion src/middlewares/requestValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import { ZodError, type ZodSchema } from 'zod'
export const requestBodyValidator = <T extends ZodSchema>(schema: T) => {
return (req: Request, res: Response, next: NextFunction) => {
try {
schema.parse(req.body)
if (req.body.data) {
schema.parse(JSON.parse(req.body.data))
} else {
schema.parse(req.body)
}
next()
} catch (err) {
console.log(err)
Expand Down
10 changes: 9 additions & 1 deletion src/routes/admin/mentor/mentor.route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
mentorDetailsHandler,
mentorStatusHandler,
searchMentors,
updateMentorAvailability
updateMentorAvailability,
updateMentorHandler
} from '../../../controllers/admin/mentor.controller'
import { requireAuth } from '../../../controllers/auth.controller'
import {
Expand All @@ -16,13 +17,20 @@ import {
getAllMentorEmailsSchema,
getAllMentorsByStatusSchema,
mentorStatusSchema,
mentorUpdateSchema,
searchMentorsSchema,
updateMentorAvailabilitySchema
} from '../../../schemas/admin/admin.mentor-routes.schema'
import { paginationSchema } from '../../../schemas/common/pagination-request.schema'
import { upload } from '../../../utils'

const mentorRouter = express.Router()

mentorRouter.put(
'/:mentorId',
[requireAuth, upload, requestBodyValidator(mentorUpdateSchema)],
updateMentorHandler
)
mentorRouter.put(
'/:mentorId/state',
[requireAuth, requestBodyValidator(mentorStatusSchema)],
Expand Down
9 changes: 9 additions & 0 deletions src/schemas/admin/admin.mentor-routes.schema.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { z } from 'zod'
import { MentorApplicationStatus } from '../../enums'
import { updateProfileSchema } from '../profile-routes.schema'

export const mentorStatusSchema = z.object({
state: z.nativeEnum(MentorApplicationStatus)
Expand All @@ -20,3 +21,11 @@ export const updateMentorAvailabilitySchema = z.object({
export const searchMentorsSchema = z.object({
q: z.string().or(z.undefined())
})

export const mentorUpdateSchema = z.object({
availability: z.boolean().optional(),
application: z.record(z.string(), z.any()).optional(),
state: z.nativeEnum(MentorApplicationStatus).optional(),
category: z.string().uuid().optional(),
profile: updateProfileSchema.optional()
})
104 changes: 103 additions & 1 deletion src/services/admin/mentor.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { dataSource } from '../../configs/dbConfig'
import Category from '../../entities/category.entity'
import Mentor from '../../entities/mentor.entity'
import Profile from '../../entities/profile.entity'
import type { MentorApplicationStatus } from '../../enums'
import { type PaginatedApiResponse } from '../../types'
import { type CreateProfile, type PaginatedApiResponse } from '../../types'
import { getEmailContent } from '../../utils'
import { sendEmail } from './email.service'

Expand Down Expand Up @@ -54,6 +56,106 @@ export const updateMentorStatus = async (
}
}

export const updateMentorDetails = async (
mentorId: string,
mentorData: Partial<Mentor>,
profileData?: Partial<Profile>
): Promise<{
statusCode: number
mentor?: Mentor | null
message: string
}> => {
try {
const mentorRepository = dataSource.getRepository(Mentor)
const profileRepository = dataSource.getRepository(Profile)
const categoryRepository = dataSource.getRepository(Category)

const mentor = await mentorRepository.findOne({
where: { uuid: mentorId },
relations: ['profile']
})

if (!mentor) {
return {
statusCode: 404,
message: 'Mentor not found'
}
}

if (mentorData.availability !== undefined) {
mentor.availability = mentorData.availability
}

if (mentorData.state) {
mentor.state = mentorData.state
}

if (mentorData.category) {
if (typeof mentorData.category === 'string') {
const category = await categoryRepository.findOne({
where: { uuid: mentorData.category }
})

if (!category) {
return {
statusCode: 404,
message: 'Category not found'
}
}
mentor.category = category
}
}

// will override values of keys if exisitng keys provided. add new key-value pairs if not exists
if (mentorData.application) {
mentor.application = {
...mentor.application,
...mentorData.application
}
}

await mentorRepository.save(mentor)

if (profileData && mentor.profile) {
const updatedProfileData: Partial<Profile> = {}

if (profileData.primary_email) {
updatedProfileData.primary_email = profileData.primary_email
}
if (profileData.first_name) {
updatedProfileData.first_name = profileData.first_name
}
if (profileData.last_name) {
updatedProfileData.last_name = profileData.last_name
}
if (profileData.image_url) {
updatedProfileData.image_url = profileData.image_url
}

if (Object.keys(updatedProfileData).length > 0) {
await profileRepository.update(
{ uuid: mentor.profile.uuid },
updatedProfileData as CreateProfile
)
}
}

const updatedMentor = await mentorRepository.findOne({
where: { uuid: mentorId },
relations: ['profile', 'category']
})

return {
statusCode: 200,
mentor: updatedMentor,
message: 'Updated Mentor details successfully'
}
} catch (err) {
console.error('Error updating the mentor details', err)
throw new Error('Error updating the mentor details')
}
}

export const getAllMentors = async ({
status,
pageNumber,
Expand Down

0 comments on commit a21e647

Please sign in to comment.