Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chat #29

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

Chat #29

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 49 additions & 21 deletions backend/Controllers/appointmentController.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,70 @@
const Appointment = require('../Models/Appointment');
const sendEmail = require('../Utils/email');
const Doctor = require('../Models/Doctor');
const Patient = require('../Models/Patient');

const addAppointment = async (req, res) => {
const { patient, doctor, date} = req.query;
const { patient, doctor, date } = req.query;

if (!patient || !doctor || !date) return res.status(400).json('There are null values');

try {

let newAppointment;

if(patient == 'Me'){
newAppointment = await Appointment.create({patient: req.user.username, doctor: doctor, date: date, });
if (patient == 'Me') {
newAppointment = await Appointment.create({ patient: req.user.username, doctor: doctor, date: date });

const tempDoctor = await Doctor.findOneAndUpdate(
{ username: doctor },
{$pull: { availableSlots: date }, $addToSet: { registeredPatients: req.user._id }},
{ $pull: { availableSlots: date }, $addToSet: { registeredPatients: req.user._id } },
{ new: true }
).exec();
}
else{
newAppointment = await Appointment.create({patient: patient, doctor: doctor, date: date, });

try {
sendEmail({
subject: 'appointment booked',
email: req.user.email,
message: `an appointment was booked successfully with Dr. ${tempDoctor.name} at ${date}.`,
});

sendEmail({
subject: 'appointment booked',
email: tempDoctor.email,
message: `${req.user.name} booked an appointment with you at ${date}.`,
});
} catch (err) {
console.log(err.message);
}
} else {
newAppointment = await Appointment.create({ patient: patient, doctor: doctor, date: date });

const tempDoctor = await Doctor.findOneAndUpdate(
{ username: doctor },
{$pull: { availableSlots: date }},
{ $pull: { availableSlots: date } },
{ new: true }
).exec();
}


const patientTarget = await Patient.findOne({ username: patient });

try {
sendEmail({
subject: 'appointment booked',
email: patientTarget.email,
message: `an appointment was booked successfully with Dr. ${tempDoctor.name} at ${date}.`,
});

sendEmail({
subject: 'appointment booked',
email: tempDoctor.email,
message: `${patientTarget.name} booked an appointment with you at ${date}.`,
});
} catch (err) {
console.log(err.message);
}
}

// console.log(newAppointment);
res.status(200).json('Appointment created successfully!');

} catch {
res.status(500).json('Appointment not created successfully!');
}
Expand All @@ -46,32 +77,29 @@ const filterAppointments = async (req, res, allAppointments) => {
const { startDate, endDate, status } = req.query;

// Validate the targetDates and status
if ((!startDate && endDate) || (startDate && !endDate) )
return res.status(400).json('There are null values.');
if ((!startDate && endDate) || (startDate && !endDate)) return res.status(400).json('There are null values.');

try {
let foundAppointment;

if(!startDate && !endDate && !status){

if (!startDate && !endDate && !status) {
foundAppointment = allAppointments;

} else if (!status) {
// Filter appointments by date with the provided targetDates
foundAppointment = allAppointments.filter((appointment) => {
foundAppointment = allAppointments.filter(appointment => {
const appointmentDate = new Date(appointment.date);
return appointmentDate >= new Date(startDate) && appointmentDate <= new Date(endDate);
});

//console.log("dates only");
} else if (!startDate && !endDate) {
// Filter appointments by status
foundAppointment = allAppointments.filter((appointment) => appointment.status === status);
foundAppointment = allAppointments.filter(appointment => appointment.status === status);

//console.log("status only");
} else {
// Filter appointments by both targetDates & status
foundAppointment = allAppointments.filter((appointment) => {
foundAppointment = allAppointments.filter(appointment => {
const appointmentDate = new Date(appointment.date);
return (
appointmentDate >= new Date(startDate) &&
Expand All @@ -92,4 +120,4 @@ const filterAppointments = async (req, res, allAppointments) => {
}
};

module.exports = { addAppointment, filterAppointments };
module.exports = { addAppointment, filterAppointments };
82 changes: 82 additions & 0 deletions backend/Controllers/chatController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
const Chat = require('../Models/Chat');
const Message = require('../Models/Message');
const Appointment = require('../Models/Appointment');

exports.getChat = async (req, res) => {
// search for the chat by the 2 users (req.user._id) and doctor id
const receiver = req.params.receiver;
console.log('params => ' + receiver);
let chat;
let newChat;
if (req.role === 'doctor') {
const appointments = await Appointment.find({ patient: receiver, doctor: req.user.username });
chat = await Chat.findOne({ patient: receiver, doctor: req.user.username });
if (chat) {
res.status(200).json({ chat });
} else if (appointments) {
newChat = await Chat.create({ patient: receiver, doctor: req.user.username });
res.status(200).json({ newChat });
} else {
res.status(200).json({});
}
} else if (req.role === 'patient') {
const appointments = await Appointment.find({ patient: req.user.username, doctor: receiver });
chat = await Chat.findOne({ patient: req.user.username, doctor: receiver });
if (chat) {
res.status(200).json({ chat });
} else if (appointments) {
newChat = await Chat.create({ patient: req.user.username, doctor: receiver });
res.status(200).json({ newChat });
} else {
res.status(200).json({});
}
}
// if chat exists return it as a response
// if not create a new chat between the 2 and save it into the db
};

exports.getChatsByUserId = async (req, res) => {
// search the chat model in the db for chats by the user id
let chats;
if (req.role === 'doctor') {
chats = await Chat.find({ doctor: req.user.username }).sort({ updatedAt: -1 });
} else if (req.role === 'patient') {
chats = await Chat.find({ patient: req.user.username }).sort({ updatedAt: -1 });
}

res.status(200).json({ chats });
// the user type can be known from the data of logged in user
// sort the chats by the updatedAt timestamp
// return the chats if present else return empty array of chats
};

exports.sendMessage = async (req, res) => {
const { content, chatId } = req.body;

if (!content || !chatId) {
console.log('Invalid data passed into request');
return res.status(400).json({ message: 'Invalid data passed into request' });
}

const newMessage = {
sender: req.user.username,
content: content,
chat: chatId,
};

const messageSent = await Message.create(newMessage);
res.status(201).json({
status: 'success. message sent.',
messageSent,
});
// the chat id is needed
// message content is needed
// create the new message object
// add it to the messages array of the chat
};

exports.getMessagesByChatId = async (req, res) => {
const chatId = req.params.chatId;
const messages = await Message.find({ chat: chatId }).sort({ updatedAt: 1 });
res.status(200).json({ status: 'success. chat messages retrieved', messages });
};
23 changes: 23 additions & 0 deletions backend/Controllers/notificationController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const Notification = require('../Models/Notification');

exports.addNotification = async (req, res) => {
// const {content, username, role} = req.body;

const newNotification = await Notification.create(req.body);

res.status(201).json({
status: 'success. notification sent.',
newNotification,
});
};

exports.getNotificationsByUsername = async (req, res) => {
const username = req.params.username;
// console.log(username);
const notifications = await Notification.find({ receiver: username });

res.status(200).json({
status: 'success. notifications retrieved.',
notifications,
});
};
5 changes: 3 additions & 2 deletions backend/Middlewares/authMiddlewares.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ exports.protect = async (req, res, next) => {
token = req.cookies.jwt;
console.log('token: ' + token);
}
console.log(token == null);
//console.log(token == null);
if (!token) {
return next(new Error(`your're not logged in. Please log in`));
}

const decoded = await promisify(jwt.verify)(token, process.env.JWT_SECRET);
console.log('role: ' + decoded.role);
//console.log('role: ' + decoded.role);
let currentUser;
if (decoded.role === 'doctor') currentUser = await Doctor.findById(decoded.id);
else if (decoded.role === 'patient') currentUser = await Patient.findById(decoded.id);
Expand All @@ -29,6 +29,7 @@ exports.protect = async (req, res, next) => {
message: `this user doesn't exist`,
});
} else {
req.role = decoded.role;
req.user = currentUser;
next();
}
Expand Down
20 changes: 20 additions & 0 deletions backend/Models/Chat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const mongoose = require('mongoose');

const chatModel = mongoose.Schema(
{
// chatName: { type: String, trim: true },
patient: {
type: String,
required: true,
},
doctor: {
type: String,
required: true,
},
},
{ timestamps: true }
);

const Chat = mongoose.model('Chat', chatModel);

module.exports = Chat;
14 changes: 14 additions & 0 deletions backend/Models/Message.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const mongoose = require('mongoose');

const messageSchema = mongoose.Schema(
{
sender: { type: String },
content: { type: String, trim: true },
chat: { type: mongoose.Schema.Types.ObjectId, ref: 'Chat' },
// readBy: [{ type: mongoose.Schema.Types.ObjectId, ref: "User" }],
},
{ timestamps: true }
);

const Message = mongoose.model('Message', messageSchema);
module.exports = Message;
23 changes: 23 additions & 0 deletions backend/Models/Notification.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const mongoose = require('mongoose');

const notificationModel = mongoose.Schema(
{
receiver: {
type: String,
required: true,
},
role: {
type: String,
required: true,
},
content: {
type: String,
required: true,
},
},
{ timestamps: true }
);

const notification = mongoose.model('Notification', notificationModel);

module.exports = notification;
32 changes: 32 additions & 0 deletions backend/Routes/chatRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const express = require('express');
const chatController = require('../Controllers/chatController');
const authMiddlewares = require('../Middlewares/authMiddlewares');

const router = express.Router();

router.get(
'/search/:receiver',
authMiddlewares.protect,
authMiddlewares.restrictTo('doctor', 'patient'),
chatController.getChat
);
router.get(
'/my-chats',
authMiddlewares.protect,
authMiddlewares.restrictTo('doctor', 'patient'),
chatController.getChatsByUserId
);
router.post(
'/send-message',
authMiddlewares.protect,
authMiddlewares.restrictTo('doctor', 'patient'),
chatController.sendMessage
);
router.get(
'/:chatId',
authMiddlewares.protect,
authMiddlewares.restrictTo('doctor', 'patient'),
chatController.getMessagesByChatId
);

module.exports = router;
16 changes: 16 additions & 0 deletions backend/Routes/notificationRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const express = require('express');
const notificationController = require('../Controllers/notificationController');
const authMiddlewares = require('../Middlewares/authMiddlewares');

const router = express.Router();

router.post('/add', notificationController.addNotification);

router.get(
'/:username',
authMiddlewares.protect,
authMiddlewares.restrictTo('doctor', 'patient'),
notificationController.getNotificationsByUsername
);

module.exports = router;
Loading