From 8e33974c624e6bcfd848f57d074cca74bd6700d6 Mon Sep 17 00:00:00 2001 From: Mark Mahrous Date: Wed, 25 Oct 2023 20:31:11 +0300 Subject: [PATCH 1/4] handling backend of task 24 and 60 and I'll do 42 and 43 later --- server/src/routes/doctor.route.ts | 13 +++++++ server/src/routes/me.route.ts | 15 ++++++-- server/src/routes/patient.route.ts | 16 ++++---- server/src/services/appointment.service.ts | 28 ++++++++++++++ server/src/services/patient.service.ts | 44 +++++++++++++++++++++- 5 files changed, 103 insertions(+), 13 deletions(-) diff --git a/server/src/routes/doctor.route.ts b/server/src/routes/doctor.route.ts index feabf37..7788f7f 100644 --- a/server/src/routes/doctor.route.ts +++ b/server/src/routes/doctor.route.ts @@ -2,8 +2,10 @@ import express, { Request, Response } from 'express'; import controller from '../controllers'; import { getDoctors } from '../services'; +import { isAuthenticated, isAuthorized } from '../middlewares'; const router = express.Router(); +router.use(isAuthenticated); router.get('/:id', (req: Request, res: Response) => { controller(res)(getDoctors)({ _id: req.params.id }); @@ -13,4 +15,15 @@ router.get('/', (req: Request, res: Response) => { controller(res)(getDoctors)(req.query); }); +//I'll edit them later +/* +router.get('/:id/appointments', isAuthorized('Patient'), (req: Request, res: Response) => { + controller(res)(getDoctorAppointments)(req.decoded.id, req.params.id); +}); + +router.post('/:id/appointments', (req: Request, res: Response) => { + controller(res)(createAppointment)(req.decoded.id, req.params.id, req.body); +}); +*/ + export default router; diff --git a/server/src/routes/me.route.ts b/server/src/routes/me.route.ts index 729eabb..268c12a 100644 --- a/server/src/routes/me.route.ts +++ b/server/src/routes/me.route.ts @@ -2,7 +2,15 @@ import express, { Request, Response } from 'express'; import controller from '../controllers'; import { isAuthenticated, isAuthorized } from '../middlewares'; -import { getUsers, updateInfo, getAppointments, getPrescriptions, addFamilyMember, getFamily } from '../services'; +import { + getUsers, + updateInfo, + getAppointments, + getPrescriptions, + addFamilyMember, + getFamily, + getHealthRecords +} from '../services'; const router = express.Router(); @@ -58,9 +66,10 @@ router.get('/prescriptions', (req: Request, res: Response) => { controller(res)(getPrescriptions)(req.query); }); -router.get('/medicalhistory', (req: Request, res: Response) => { - // controller(res)()(); +router.get('/medicalhistory', isAuthorized('Patient'), (req: Request, res: Response) => { + controller(res)(getHealthRecords)(req.decoded.id); }); + router.post('/medicalhistory', (req: Request, res: Response) => { // controller(res)()(); }); diff --git a/server/src/routes/patient.route.ts b/server/src/routes/patient.route.ts index e0a1202..cf0ebca 100644 --- a/server/src/routes/patient.route.ts +++ b/server/src/routes/patient.route.ts @@ -1,7 +1,7 @@ import express, { Request, Response } from 'express'; import controller from '../controllers'; -import { getMyPatients } from '../services'; +import { addHealthRecord, getHealthRecords, getMyPatients } from '../services'; import { isAuthenticated, isAuthorized } from '../middlewares'; const router = express.Router(); @@ -9,10 +9,6 @@ const router = express.Router(); router.use(isAuthenticated); router.use(isAuthorized('Doctor')); -router.get('/:id/medicalhistory', (req: Request, res: Response) => { - // controller(res)()(); -}); - router.get('/:id', (req: Request, res: Response) => { controller(res)(getMyPatients)({ doctorID: req.decoded.id, patientID: req.params.id }); }); @@ -20,10 +16,12 @@ router.get('/', (req: Request, res: Response) => { controller(res)(getMyPatients)({ doctorID: req.decoded.id }); }); -router.post('/:id/medicalhistory', (req: Request, res: Response) => { - // Handle medical history update logic here - // notice that doctors can update patients medical history - // controller(res)()(); +router.get('/:id/medicalhistory', isAuthorized('Doctor'), (req: Request, res: Response) => { + controller(res)(getHealthRecords)(req.params.id); +}); + +router.post('/:id/medicalhistory', isAuthorized('Doctor'), (req: Request, res: Response) => { + controller(res)(addHealthRecord)(req.params.id, req.body); }); export default router; diff --git a/server/src/services/appointment.service.ts b/server/src/services/appointment.service.ts index 45b494d..63f0345 100644 --- a/server/src/services/appointment.service.ts +++ b/server/src/services/appointment.service.ts @@ -18,4 +18,32 @@ const getAppointments = async (query: any) => { }; }; +//I'll edit them later +/* +const createAppointment = async (patientID: String, doctorID: String, body: any) => { + body.patientID = patientID; + body.doctorID = doctorID; + const newAppointment = await Appointment.create(body); + + return { + status: StatusCodes.CREATED, + message: 'Appointment created successfully', + result: newAppointment + }; +}; + +const getDoctorAppointments = async (patientID: String, doctorID: String) => { + const appointments = await Appointment.find({ doctorID }); + + if (!appointments) throw new HttpError(StatusCodes.NOT_FOUND, 'No available appointments for this doctor'); + + return { + status: StatusCodes.OK, + message: 'Appointments retrieved successfully', + result: appointments + }; +}; +export { getAppointments, createAppointment, getDoctorAppointments }; +*/ + export { getAppointments }; diff --git a/server/src/services/patient.service.ts b/server/src/services/patient.service.ts index 5412e50..a64bc97 100644 --- a/server/src/services/patient.service.ts +++ b/server/src/services/patient.service.ts @@ -98,4 +98,46 @@ const viewDoctorsForPatient = async (patientId: string, query: any) => { }; }; -export { viewDoctorsForPatient as viewAllDoctorsForPatient, getFamily, addFamilyMember }; +const addHealthRecord = async (patientID: String, body: any) => { + const { name, medicalRecord } = body; + if (!name || !medicalRecord) throw new HttpError(StatusCodes.BAD_REQUEST, 'Please provide name, medicalRecord'); + + const update = { + $push: { + medicalHistory: { + name, + medicalRecord + } + } + }; + const updatedUser = await Patient.findByIdAndUpdate(patientID, update, { new: true }); + if (!updatedUser) throw new HttpError(StatusCodes.NOT_FOUND, 'User not found'); + + return { + result: updatedUser, + status: StatusCodes.OK, + message: 'Health record added successfully' + }; +}; + +const getHealthRecords = async (patientID: String) => { + const user: any = await Patient.findById(patientID).select('medicalHistory'); + if (!user) throw new HttpError(StatusCodes.NOT_FOUND, 'patient not found'); + + const healthRecords = user.medicalHistory; + if (!healthRecords) throw new HttpError(StatusCodes.NOT_FOUND, 'health records not found'); + + return { + result: healthRecords, + status: StatusCodes.OK, + message: 'Health records retrieved successfully' + }; +}; + +export { + viewDoctorsForPatient as viewAllDoctorsForPatient, + getFamily, + addFamilyMember, + addHealthRecord, + getHealthRecords +}; From 55b53332224bdc24c144996ef56b1da3bbc194e4 Mon Sep 17 00:00:00 2001 From: Mark Mahrous Date: Mon, 6 Nov 2023 15:29:40 +0200 Subject: [PATCH 2/4] done with backend of 42&43 tasks --- server/src/models/doctor.model.ts | 7 +--- server/src/routes/doctor.route.ts | 21 +++++------ server/src/services/appointment.service.ts | 43 +++++++++++++--------- server/src/services/doctor.service.ts | 38 ++++++++++++++++++- 4 files changed, 73 insertions(+), 36 deletions(-) diff --git a/server/src/models/doctor.model.ts b/server/src/models/doctor.model.ts index aae3651..cf6bad6 100644 --- a/server/src/models/doctor.model.ts +++ b/server/src/models/doctor.model.ts @@ -6,7 +6,7 @@ const options = { discriminatorKey: 'role' }; interface DailySchedule { from: { hours: number; minutes: number }; to: { hours: number; minutes: number }; - maxPatients: number; + isReserved: boolean; } interface IDoctor extends ICommonUser { @@ -50,10 +50,7 @@ const dailyScheduleSchema = { }, required: true }, - maxPatients: { - type: Number, - required: true - } + isReserved: { type: Boolean, default: false } }; const doctorSchema = new Schema( diff --git a/server/src/routes/doctor.route.ts b/server/src/routes/doctor.route.ts index 7788f7f..1610219 100644 --- a/server/src/routes/doctor.route.ts +++ b/server/src/routes/doctor.route.ts @@ -1,29 +1,26 @@ import express, { Request, Response } from 'express'; import controller from '../controllers'; -import { getDoctors } from '../services'; +import { createAppointment, getDoctors, viewAvailableAppointments } from '../services'; import { isAuthenticated, isAuthorized } from '../middlewares'; const router = express.Router(); router.use(isAuthenticated); -router.get('/:id', (req: Request, res: Response) => { - controller(res)(getDoctors)({ _id: req.params.id }); +router.get('/:id/availableAppointments', isAuthorized('Patient'), (req: Request, res: Response) => { + controller(res)(viewAvailableAppointments)(req.params.id); }); -router.get('/', (req: Request, res: Response) => { - controller(res)(getDoctors)(req.query); +router.post('/:id/appointments', isAuthorized('Patient'), (req: Request, res: Response) => { + controller(res)(createAppointment)(req.decoded.id, req.params.id, req.body); }); -//I'll edit them later -/* -router.get('/:id/appointments', isAuthorized('Patient'), (req: Request, res: Response) => { - controller(res)(getDoctorAppointments)(req.decoded.id, req.params.id); +router.get('/:id', (req: Request, res: Response) => { + controller(res)(getDoctors)({ _id: req.params.id }); }); -router.post('/:id/appointments', (req: Request, res: Response) => { - controller(res)(createAppointment)(req.decoded.id, req.params.id, req.body); +router.get('/', (req: Request, res: Response) => { + controller(res)(getDoctors)(req.query); }); -*/ export default router; diff --git a/server/src/services/appointment.service.ts b/server/src/services/appointment.service.ts index 63f0345..ff80508 100644 --- a/server/src/services/appointment.service.ts +++ b/server/src/services/appointment.service.ts @@ -1,4 +1,4 @@ -import { Appointment } from '../models'; +import { Appointment, Doctor } from '../models'; import { StatusCodes } from 'http-status-codes'; import mongoose from 'mongoose'; import { HttpError } from '../utils'; @@ -18,13 +18,34 @@ const getAppointments = async (query: any) => { }; }; -//I'll edit them later -/* const createAppointment = async (patientID: String, doctorID: String, body: any) => { + const doctor = await Doctor.findById(doctorID); + if (!doctor) throw new HttpError(StatusCodes.NOT_FOUND, 'Doctor not found'); + + const weeklySlots = doctor.weeklySlots; + if (!weeklySlots) throw new HttpError(StatusCodes.NOT_FOUND, 'No available appointments for this doctor'); + body.patientID = patientID; body.doctorID = doctorID; const newAppointment = await Appointment.create(body); + const daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; + const dayOfWeek = daysOfWeek[newAppointment.startDate.getDay()]; + // console.log(dayOfWeek); + const dailySlots = weeklySlots[dayOfWeek as keyof typeof weeklySlots]; + for (let i = 0; i < dailySlots.length; i++) { + const slot = dailySlots[i]; + // console.log(slot.from.hours); + // console.log(body.from.hours); + // console.log(slot.from.minutes); + // console.log(body.from.minutes); + if (slot.from.hours === body.from.hours && slot.from.minutes === body.from.minutes) { + slot.isReserved = true; + await doctor.save(); + break; + } + } + return { status: StatusCodes.CREATED, message: 'Appointment created successfully', @@ -32,18 +53,4 @@ const createAppointment = async (patientID: String, doctorID: String, body: any) }; }; -const getDoctorAppointments = async (patientID: String, doctorID: String) => { - const appointments = await Appointment.find({ doctorID }); - - if (!appointments) throw new HttpError(StatusCodes.NOT_FOUND, 'No available appointments for this doctor'); - - return { - status: StatusCodes.OK, - message: 'Appointments retrieved successfully', - result: appointments - }; -}; -export { getAppointments, createAppointment, getDoctorAppointments }; -*/ - -export { getAppointments }; +export { getAppointments, createAppointment }; diff --git a/server/src/services/doctor.service.ts b/server/src/services/doctor.service.ts index bdc4e25..681ed6f 100644 --- a/server/src/services/doctor.service.ts +++ b/server/src/services/doctor.service.ts @@ -44,4 +44,40 @@ const getDoctors = async (query: any) => { return { result: doctors, status: StatusCodes.OK }; }; -export { getDoctors, getMyPatients }; +const viewAvailableAppointments = async (doctorID: string) => { + const doctor = await Doctor.findById(doctorID); + if (!doctor) throw new HttpError(StatusCodes.NOT_FOUND, 'Doctor not found'); + + const weeklySlots = doctor.weeklySlots; + if (!weeklySlots) throw new HttpError(StatusCodes.NOT_FOUND, 'No available appointments for this doctor'); + + let availableAppointments: any = {}; + + const daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; + + for (const dayOfWeek of daysOfWeek) { + const dailySlots = weeklySlots[dayOfWeek as keyof typeof weeklySlots]; + let dailyAppointments = []; + + for (const slot of dailySlots) { + if (!slot.isReserved) { + dailyAppointments.push({ + from: `${slot.from.hours}:${slot.from.minutes}`, + to: `${slot.to.hours}:${slot.to.minutes}` + }); + } + } + + if (dailyAppointments.length > 0) { + availableAppointments[dayOfWeek] = dailyAppointments; + } + } + + return { + status: StatusCodes.OK, + message: 'Available Appointments retrieved successfully', + result: availableAppointments + }; +}; + +export { getDoctors, getMyPatients, viewAvailableAppointments }; From 4444cb68c13a394d1440edb2b6665364f7ea176d Mon Sep 17 00:00:00 2001 From: Mark Mahrous Date: Wed, 8 Nov 2023 00:13:18 +0200 Subject: [PATCH 3/4] edit task 42 & 43 --- server/src/models/doctor.model.ts | 4 +- server/src/services/appointment.service.ts | 20 ------- server/src/services/doctor.service.ts | 69 ++++++++++++++++------ 3 files changed, 52 insertions(+), 41 deletions(-) diff --git a/server/src/models/doctor.model.ts b/server/src/models/doctor.model.ts index cf6bad6..ef39182 100644 --- a/server/src/models/doctor.model.ts +++ b/server/src/models/doctor.model.ts @@ -6,7 +6,6 @@ const options = { discriminatorKey: 'role' }; interface DailySchedule { from: { hours: number; minutes: number }; to: { hours: number; minutes: number }; - isReserved: boolean; } interface IDoctor extends ICommonUser { @@ -49,8 +48,7 @@ const dailyScheduleSchema = { minutes: { type: Number, required: false, default: 0, min: 0, max: 59 } }, required: true - }, - isReserved: { type: Boolean, default: false } + } }; const doctorSchema = new Schema( diff --git a/server/src/services/appointment.service.ts b/server/src/services/appointment.service.ts index ff80508..0ec7821 100644 --- a/server/src/services/appointment.service.ts +++ b/server/src/services/appointment.service.ts @@ -22,30 +22,10 @@ const createAppointment = async (patientID: String, doctorID: String, body: any) const doctor = await Doctor.findById(doctorID); if (!doctor) throw new HttpError(StatusCodes.NOT_FOUND, 'Doctor not found'); - const weeklySlots = doctor.weeklySlots; - if (!weeklySlots) throw new HttpError(StatusCodes.NOT_FOUND, 'No available appointments for this doctor'); - body.patientID = patientID; body.doctorID = doctorID; const newAppointment = await Appointment.create(body); - const daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; - const dayOfWeek = daysOfWeek[newAppointment.startDate.getDay()]; - // console.log(dayOfWeek); - const dailySlots = weeklySlots[dayOfWeek as keyof typeof weeklySlots]; - for (let i = 0; i < dailySlots.length; i++) { - const slot = dailySlots[i]; - // console.log(slot.from.hours); - // console.log(body.from.hours); - // console.log(slot.from.minutes); - // console.log(body.from.minutes); - if (slot.from.hours === body.from.hours && slot.from.minutes === body.from.minutes) { - slot.isReserved = true; - await doctor.save(); - break; - } - } - return { status: StatusCodes.CREATED, message: 'Appointment created successfully', diff --git a/server/src/services/doctor.service.ts b/server/src/services/doctor.service.ts index 681ed6f..5bcf002 100644 --- a/server/src/services/doctor.service.ts +++ b/server/src/services/doctor.service.ts @@ -51,26 +51,59 @@ const viewAvailableAppointments = async (doctorID: string) => { const weeklySlots = doctor.weeklySlots; if (!weeklySlots) throw new HttpError(StatusCodes.NOT_FOUND, 'No available appointments for this doctor'); - let availableAppointments: any = {}; - - const daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; - - for (const dayOfWeek of daysOfWeek) { - const dailySlots = weeklySlots[dayOfWeek as keyof typeof weeklySlots]; - let dailyAppointments = []; - - for (const slot of dailySlots) { - if (!slot.isReserved) { - dailyAppointments.push({ - from: `${slot.from.hours}:${slot.from.minutes}`, - to: `${slot.to.hours}:${slot.to.minutes}` - }); + const availableAppointments = []; + + const thisDay = new Date(); + const currentYear = thisDay.getUTCFullYear(); + const currentMonth = thisDay.getUTCMonth(); + const currentDate = thisDay.getUTCDate(); + const currentDay = thisDay.getUTCDay(); + const lastDay = currentDay + 6; + + // Get all doctor's appointments + const appointments = await Appointment.find({ + doctorID: doctorID + }); + + for (let i = currentDay; i <= lastDay; i++) { + const dayOfWeek = i % 7; + const day = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][dayOfWeek]; + const dailySlots = weeklySlots[day as keyof typeof weeklySlots]; + const availableSlots = dailySlots.filter((slot) => { + const slotHour = slot.from.hours; + const slotMinute = slot.from.minutes; + for (let j = 0; j < appointments.length; j++) { + const appointment = appointments[j]; + const appointmentStartDate = appointment.startDate; + const appointmentYear = appointmentStartDate.getUTCFullYear(); + const appointmentMonth = appointmentStartDate.getUTCMonth(); + const appointmentDate = appointmentStartDate.getUTCDate(); + const appointmentDay = appointmentStartDate.getUTCDay(); + const appointmentHour = appointmentStartDate.getUTCHours(); + const appointmentMinute = appointmentStartDate.getUTCMinutes(); + // Check if the appointment is between the current date and the next 7 days + if ( + appointmentYear === currentYear && + appointmentMonth === currentMonth && + appointmentDate >= currentDate && + appointmentDate <= currentDate + 6 && + appointmentDay % 7 === dayOfWeek && + slotHour === appointmentHour && + slotMinute === appointmentMinute + ) { + return false; + } } - } + return true; + }); + + const fullDate = new Date(currentYear, currentMonth, currentDate + 1 + i - currentDay); - if (dailyAppointments.length > 0) { - availableAppointments[dayOfWeek] = dailyAppointments; - } + availableAppointments.push({ + day, + date: fullDate, + slots: availableSlots + }); } return { From 785f3d9e15102f24a0c900a792df6639445a1e21 Mon Sep 17 00:00:00 2001 From: Mark Mahrous Date: Wed, 8 Nov 2023 12:56:22 +0200 Subject: [PATCH 4/4] edit get available appointments function --- server/src/services/doctor.service.ts | 53 ++++++++++++++++++++------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/server/src/services/doctor.service.ts b/server/src/services/doctor.service.ts index 5bcf002..6f39f04 100644 --- a/server/src/services/doctor.service.ts +++ b/server/src/services/doctor.service.ts @@ -69,11 +69,15 @@ const viewAvailableAppointments = async (doctorID: string) => { const dayOfWeek = i % 7; const day = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][dayOfWeek]; const dailySlots = weeklySlots[day as keyof typeof weeklySlots]; - const availableSlots = dailySlots.filter((slot) => { + + for (const slot of dailySlots) { const slotHour = slot.from.hours; const slotMinute = slot.from.minutes; - for (let j = 0; j < appointments.length; j++) { - const appointment = appointments[j]; + const slotHourEnd = slot.to.hours; + const slotMinuteEnd = slot.to.minutes; + let isSlotAvailable = true; + + for (const appointment of appointments) { const appointmentStartDate = appointment.startDate; const appointmentYear = appointmentStartDate.getUTCFullYear(); const appointmentMonth = appointmentStartDate.getUTCMonth(); @@ -81,7 +85,7 @@ const viewAvailableAppointments = async (doctorID: string) => { const appointmentDay = appointmentStartDate.getUTCDay(); const appointmentHour = appointmentStartDate.getUTCHours(); const appointmentMinute = appointmentStartDate.getUTCMinutes(); - // Check if the appointment is between the current date and the next 7 days + if ( appointmentYear === currentYear && appointmentMonth === currentMonth && @@ -91,19 +95,40 @@ const viewAvailableAppointments = async (doctorID: string) => { slotHour === appointmentHour && slotMinute === appointmentMinute ) { - return false; + isSlotAvailable = false; + break; } } - return true; - }); - const fullDate = new Date(currentYear, currentMonth, currentDate + 1 + i - currentDay); - - availableAppointments.push({ - day, - date: fullDate, - slots: availableSlots - }); + if (isSlotAvailable) { + const startDate = new Date( + currentYear, + currentMonth, + currentDate + i - currentDay, + slotHour + 2, + slotMinute, + 0, + 0 + ); + const endDate = new Date( + currentYear, + currentMonth, + currentDate + i - currentDay, + slotHourEnd + 2, + slotMinuteEnd, + 0, + 0 + ); + + availableAppointments.push({ + status: 'Upcoming', + sessionPrice: 50, + startDate: startDate.toISOString(), + endDate: endDate.toISOString(), + isFollowUp: true + }); + } + } } return {