Files
gg-backend/backend/src/controllers/appointment.controller.js
T

390 lines
8.2 KiB
JavaScript
Raw Normal View History

2026-05-26 15:48:01 +05:30
import prisma from '../prisma/client.js';
import { sendEmail } from '../utils/sendEmail.js';
import { getEmailsByType } from '../utils/getEmailByTypes.js';
2026-03-16 10:16:27 +05:30
export const createAppointment = async (req, res) => {
try {
2026-05-26 15:48:01 +05:30
const { name, mobileNumber, email, message, date, doctorId, departmentId } = req.body;
2026-03-16 10:16:27 +05:30
if (!name || !mobileNumber || !doctorId || !departmentId || !date) {
return res.status(400).json({
success: false,
2026-05-26 15:48:01 +05:30
message: 'Required fields missing',
2026-03-16 10:16:27 +05:30
});
}
const appointment = await prisma.appointment.create({
data: {
name,
mobileNumber,
email,
message,
date: new Date(date),
doctorId,
departmentId,
},
include: {
doctor: true,
department: true,
},
});
2026-03-19 13:12:04 +05:30
try {
2026-05-26 15:48:01 +05:30
const emailList = await getEmailsByType('APPOINTMENT');
2026-03-19 13:12:04 +05:30
if (emailList) {
await sendEmail({
to: emailList,
2026-05-26 15:48:01 +05:30
subject: 'New Appointment Booked',
2026-03-19 13:12:04 +05:30
html: `
2026-04-27 17:29:33 +05:30
<div style="font-family: Arial, sans-serif; background-color: #f4f6f8; padding: 20px;">
<div style="max-width: 600px; margin: auto; background: #ffffff; border-radius: 10px; overflow: hidden; box-shadow: 0 4px 10px rgba(0,0,0,0.05);">
<!-- Header -->
<div style="background-color: #0d6efd; color: #ffffff; padding: 20px;">
<h2 style="margin: 0;">GG Hospital</h2>
<p style="margin: 5px 0 0; font-size: 14px;">
New Appointment Booked
</p>
</div>
<!-- Body -->
<div style="padding: 20px; color: #333;">
<h3 style="margin-top: 0;">Patient Details</h3>
<table style="width: 100%; border-collapse: collapse;">
<tr>
<td style="padding: 8px 0;"><b>Name:</b></td>
<td style="padding: 8px 0;">${name}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Phone:</b></td>
<td style="padding: 8px 0;">${mobileNumber}</td>
</tr>
<tr>
<td style="padding: 8px 0;"><b>Email:</b></td>
2026-05-26 15:48:01 +05:30
<td style="padding: 8px 0;">${email || '-'}</td>
2026-04-27 17:29:33 +05:30
</tr>
</table>
<h3 style="margin-top: 20px;">Appointment Details</h3>
<table style="width: 100%; border-collapse: collapse;">
<tr>
<td style="padding: 8px 0;"><b>Doctor:</b></td>
2026-05-26 15:48:01 +05:30
<td style="padding: 8px 0;">${appointment.doctor?.name || '-'}</td>
2026-04-27 17:29:33 +05:30
</tr>
<tr>
<td style="padding: 8px 0;"><b>Department:</b></td>
2026-05-26 15:48:01 +05:30
<td style="padding: 8px 0;">${appointment.department?.name || '-'}</td>
2026-04-27 17:29:33 +05:30
</tr>
<tr>
<td style="padding: 8px 0;"><b>Date:</b></td>
<td style="padding: 8px 0;">
2026-05-26 15:48:01 +05:30
${new Date(date).toLocaleDateString('en-GB', {
day: '2-digit',
month: 'long',
year: 'numeric',
2026-05-13 11:57:33 +05:30
})}
</td>
2026-04-27 17:29:33 +05:30
</tr>
</table>
<!-- Message Box -->
<div style="margin-top: 20px;">
<h3>Message</h3>
<div style="
background: #f8f9fa;
padding: 15px;
border-radius: 6px;
line-height: 1.6;
white-space: pre-wrap;
word-break: break-word;
overflow-wrap: anywhere;
">
2026-05-26 15:48:01 +05:30
${message ? message.replace(/\n/g, '<br/>') : '-'}
2026-04-27 17:29:33 +05:30
</div>
</div>
</div>
<!-- Footer -->
<div style="background: #f1f1f1; padding: 15px; text-align: center; font-size: 12px; color: #666;">
This appointment was booked via the GG Hospital website.
</div>
</div>
</div>
`,
2026-03-19 13:12:04 +05:30
});
}
} catch (err) {
2026-05-26 15:48:01 +05:30
console.error('Email failed:', err);
2026-03-19 13:12:04 +05:30
}
2026-03-16 10:16:27 +05:30
res.status(201).json({
success: true,
2026-05-26 15:48:01 +05:30
message: 'Appointment booked successfully',
2026-03-16 10:16:27 +05:30
data: appointment,
});
} catch (error) {
console.error(error);
res.status(500).json({
success: false,
2026-05-26 15:48:01 +05:30
message: 'Failed to create appointment',
2026-03-16 10:16:27 +05:30
});
}
};
// GET ALL APPOINTMENTS
export const getAppointments = async (req, res) => {
try {
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 10;
const skip = (page - 1) * limit;
2026-05-13 14:20:51 +05:30
const { date, startDate, endDate, search } = req.query;
const where = {};
2026-05-26 15:48:01 +05:30
const hasSingleDate = date && date.trim() !== '';
2026-05-13 14:20:51 +05:30
2026-05-26 15:48:01 +05:30
const hasRange = (startDate && startDate.trim() !== '') || (endDate && endDate.trim() !== '');
2026-05-13 14:20:51 +05:30
if (hasSingleDate) {
const start = new Date(date);
2026-05-13 14:20:51 +05:30
start.setHours(0, 0, 0, 0);
const end = new Date(date);
2026-05-13 14:20:51 +05:30
end.setHours(23, 59, 59, 999);
where.date = {
gte: start,
lte: end,
};
}
if (!hasSingleDate && hasRange) {
const dateFilter = {};
2026-05-26 15:48:01 +05:30
if (startDate && startDate.trim() !== '') {
2026-05-13 14:20:51 +05:30
const start = new Date(startDate);
start.setHours(0, 0, 0, 0);
dateFilter.gte = start;
}
2026-05-26 15:48:01 +05:30
if (endDate && endDate.trim() !== '') {
2026-05-13 14:20:51 +05:30
const end = new Date(endDate);
end.setHours(23, 59, 59, 999);
dateFilter.lte = end;
}
where.date = dateFilter;
}
2026-05-26 15:48:01 +05:30
if (search && search.trim() !== '') {
where.OR = [
2026-05-26 15:48:01 +05:30
{ name: { contains: search, mode: 'insensitive' } },
{ mobileNumber: { contains: search } },
2026-05-26 15:48:01 +05:30
{ email: { contains: search, mode: 'insensitive' } },
];
}
const [appointments, total] = await Promise.all([
prisma.appointment.findMany({
where,
2026-05-13 14:20:51 +05:30
include: {
doctor: true,
department: true,
},
orderBy: {
2026-05-26 15:48:01 +05:30
createdAt: 'desc',
2026-05-13 14:20:51 +05:30
},
skip,
take: limit,
}),
2026-05-13 14:20:51 +05:30
prisma.appointment.count({
where,
}),
]);
2026-03-16 10:16:27 +05:30
res.status(200).json({
success: true,
data: appointments,
2026-05-13 14:20:51 +05:30
pagination: {
total,
page,
limit,
totalPages: Math.ceil(total / limit),
},
2026-03-16 10:16:27 +05:30
});
} catch (error) {
console.error(error);
2026-05-13 14:20:51 +05:30
res.status(500).json({
success: false,
2026-05-26 15:48:01 +05:30
message: 'Failed to fetch appointments',
2026-05-13 14:20:51 +05:30
});
2026-03-16 10:16:27 +05:30
}
};
// GET SINGLE APPOINTMENT
export const getAppointment = async (req, res) => {
try {
const { id } = req.params;
2026-03-16 10:16:27 +05:30
const appointment = await prisma.appointment.findUnique({
where: {
id: Number(id),
},
include: {
doctor: true,
department: true,
},
});
if (!appointment) {
return res.status(404).json({
success: false,
2026-05-26 15:48:01 +05:30
message: 'Appointment not found',
2026-03-16 10:16:27 +05:30
});
}
res.status(200).json({
success: true,
data: appointment,
});
} catch (error) {
console.error(error);
res.status(500).json({
success: false,
2026-05-26 15:48:01 +05:30
message: 'Failed to fetch appointment',
2026-03-16 10:16:27 +05:30
});
}
};
// GET APPOINTMENTS BY DOCTOR
export const getAppointmentsByDoctor = async (req, res) => {
try {
const { doctorId } = req.params;
2026-03-16 10:16:27 +05:30
const appointments = await prisma.appointment.findMany({
where: {
doctorId,
},
include: {
doctor: true,
department: true,
},
orderBy: {
2026-05-26 15:48:01 +05:30
date: 'asc',
2026-03-16 10:16:27 +05:30
},
});
res.status(200).json({
success: true,
data: appointments,
});
} catch (error) {
console.error(error);
res.status(500).json({
success: false,
2026-05-26 15:48:01 +05:30
message: 'Failed to fetch doctor appointments',
2026-03-16 10:16:27 +05:30
});
}
};
// GET APPOINTMENTS BY DEPARTMENT
export const getAppointmentsByDepartment = async (req, res) => {
try {
const { departmentId } = req.params;
2026-03-16 10:16:27 +05:30
const appointments = await prisma.appointment.findMany({
where: {
departmentId,
},
include: {
doctor: true,
department: true,
},
});
res.status(200).json({
success: true,
data: appointments,
});
} catch (error) {
console.error(error);
res.status(500).json({
success: false,
2026-05-26 15:48:01 +05:30
message: 'Failed to fetch department appointments',
2026-03-16 10:16:27 +05:30
});
}
};
// UPDATE APPOINTMENT
export const updateAppointment = async (req, res) => {
try {
const { id } = req.params;
2026-03-16 10:16:27 +05:30
const appointment = await prisma.appointment.update({
where: {
id: Number(id),
},
data: req.body,
include: {
doctor: true,
department: true,
},
});
res.status(200).json({
success: true,
2026-05-26 15:48:01 +05:30
message: 'Appointment updated successfully',
2026-03-16 10:16:27 +05:30
data: appointment,
});
} catch (error) {
console.error(error);
res.status(500).json({
success: false,
2026-05-26 15:48:01 +05:30
message: 'Failed to update appointment',
2026-03-16 10:16:27 +05:30
});
}
};
//DELETE APPOINTMENT
export const deleteAppointment = async (req, res) => {
try {
const { id } = req.params;
2026-03-16 10:16:27 +05:30
await prisma.appointment.delete({
where: {
id: Number(id),
},
});
res.status(200).json({
success: true,
2026-05-26 15:48:01 +05:30
message: 'Appointment deleted successfully',
2026-03-16 10:16:27 +05:30
});
} catch (error) {
console.error(error);
res.status(500).json({
success: false,
2026-05-26 15:48:01 +05:30
message: 'Failed to delete appointment',
2026-03-16 10:16:27 +05:30
});
}
};