diff --git a/backend/src/controllers/appointment.controller.js b/backend/src/controllers/appointment.controller.js index df316ca..36bfcdd 100644 --- a/backend/src/controllers/appointment.controller.js +++ b/backend/src/controllers/appointment.controller.js @@ -84,8 +84,12 @@ export const createAppointment = async (req, res) => { Date: - ${new Date(date).toLocaleDateString()} - + ${new Date(date).toLocaleDateString("en-GB", { + day: "2-digit", + month: "long", + year: "numeric", + })} + @@ -143,18 +147,51 @@ export const getAppointments = async (req, res) => { const page = parseInt(req.query.page) || 1; const limit = parseInt(req.query.limit) || 10; const skip = (page - 1) * limit; - const { date, search } = req.query; + + const { date, startDate, endDate, search } = req.query; const where = {}; - if (date) { + const hasSingleDate = date && date.trim() !== ""; + + const hasRange = + (startDate && startDate.trim() !== "") || + (endDate && endDate.trim() !== ""); + + if (hasSingleDate) { const start = new Date(date); + start.setHours(0, 0, 0, 0); + const end = new Date(date); - end.setDate(end.getDate() + 1); - where.date = { gte: start, lt: end }; + end.setHours(23, 59, 59, 999); + + where.date = { + gte: start, + lte: end, + }; } - if (search) { + if (!hasSingleDate && hasRange) { + const dateFilter = {}; + + if (startDate && startDate.trim() !== "") { + const start = new Date(startDate); + start.setHours(0, 0, 0, 0); + + dateFilter.gte = start; + } + + if (endDate && endDate.trim() !== "") { + const end = new Date(endDate); + end.setHours(23, 59, 59, 999); + + dateFilter.lte = end; + } + + where.date = dateFilter; + } + + if (search && search.trim() !== "") { where.OR = [ { name: { contains: search, mode: "insensitive" } }, { mobileNumber: { contains: search } }, @@ -165,24 +202,39 @@ export const getAppointments = async (req, res) => { const [appointments, total] = await Promise.all([ prisma.appointment.findMany({ where, - include: { doctor: true, department: true }, - orderBy: { createdAt: "desc" }, + include: { + doctor: true, + department: true, + }, + orderBy: { + createdAt: "desc", + }, skip, take: limit, }), - prisma.appointment.count({ where }), + + prisma.appointment.count({ + where, + }), ]); res.status(200).json({ success: true, data: appointments, - pagination: { total, page, limit, totalPages: Math.ceil(total / limit) }, + pagination: { + total, + page, + limit, + totalPages: Math.ceil(total / limit), + }, }); } catch (error) { console.error(error); - res - .status(500) - .json({ success: false, message: "Failed to fetch appointments" }); + + res.status(500).json({ + success: false, + message: "Failed to fetch appointments", + }); } }; diff --git a/backend/src/controllers/doctor.controller.js b/backend/src/controllers/doctor.controller.js index 52e619d..750d3d7 100644 --- a/backend/src/controllers/doctor.controller.js +++ b/backend/src/controllers/doctor.controller.js @@ -273,42 +273,47 @@ export const updateDoctor = async (req, res) => { }, }); - const oldRelations = await prisma.doctorDepartment.findMany({ - where: {doctorId: doctor.id}, - }); + const hasTimingData = departments?.some( + (dep) => dep.timing && Object.keys(dep.timing).length > 0, + ); - for (const rel of oldRelations) { - await prisma.doctorTiming.deleteMany({ - where: {doctorDepartmentId: rel.id}, - }); - } - - await prisma.doctorDepartment.deleteMany({ - where: {doctorId: doctor.id}, - }); - - for (const dep of departments) { - const targetDept = await prisma.department.findUnique({ - where: {departmentId: dep.departmentId}, - }); - if (!targetDept) continue; - - const newDD = await prisma.doctorDepartment.create({ - data: { - doctorId: doctor.id, - departmentId: targetDept.id, - sortOrder: dep.sortOrder !== undefined ? Number(dep.sortOrder) : 0, - }, + if (departments && Array.isArray(departments) && hasTimingData) { + const oldRelations = await prisma.doctorDepartment.findMany({ + where: {doctorId: doctor.id}, }); - if (dep.timing) { - const {id, doctorDepartmentId, createdAt, updatedAt, ...cleanTiming} = - dep.timing; - - await prisma.doctorTiming.create({ - data: {doctorDepartmentId: newDD.id, ...cleanTiming}, + for (const rel of oldRelations) { + await prisma.doctorTiming.deleteMany({ + where: {doctorDepartmentId: rel.id}, }); } + + await prisma.doctorDepartment.deleteMany({ + where: {doctorId: doctor.id}, + }); + + for (const dep of departments) { + const targetDept = await prisma.department.findUnique({ + where: {departmentId: dep.departmentId}, + }); + if (!targetDept) continue; + + const newDD = await prisma.doctorDepartment.create({ + data: { + doctorId: doctor.id, + departmentId: targetDept.id, + sortOrder: dep.sortOrder !== undefined ? Number(dep.sortOrder) : 0, + }, + }); + + if (dep.timing) { + const {id, doctorDepartmentId, createdAt, updatedAt, ...cleanTiming} = + dep.timing; + await prisma.doctorTiming.create({ + data: {doctorDepartmentId: newDD.id, ...cleanTiming}, + }); + } + } } res diff --git a/frontend/src/api/appointment.ts b/frontend/src/api/appointment.ts index 5a7d90e..eb346a5 100644 --- a/frontend/src/api/appointment.ts +++ b/frontend/src/api/appointment.ts @@ -4,12 +4,16 @@ export const getAppointmentsApi = async ( page = 1, limit = 10, date = "", + startDate = "", + endDate = "", search = "", ) => { const params = new URLSearchParams({ page: String(page), limit: String(limit), ...(date && { date }), + ...(startDate && { startDate }), + ...(endDate && { endDate }), ...(search && { search }), }); const res = await apiClient.get(`/appointments/getall?${params}`); diff --git a/frontend/src/api/doctor.ts b/frontend/src/api/doctor.ts index 7e1b1df..d7ae82f 100644 --- a/frontend/src/api/doctor.ts +++ b/frontend/src/api/doctor.ts @@ -8,8 +8,10 @@ export interface Doctor { designation?: string; workingStatus?: string; qualification?: string; + isActive: boolean; + globalSortOrder: number; - departments: { + departments?: { departmentId: string; timing?: { monday?: string; diff --git a/frontend/src/pages/Appointment.tsx b/frontend/src/pages/Appointment.tsx index 5863afd..77215cd 100644 --- a/frontend/src/pages/Appointment.tsx +++ b/frontend/src/pages/Appointment.tsx @@ -40,7 +40,8 @@ export default function AppointmentPage() { const [searchText, setSearchText] = useState(""); const [filterDoctor, setFilterDoctor] = useState(""); const [filterDate, setFilterDate] = useState(""); - + const [startDate, setStartDate] = useState(""); + const [endDate, setEndDate] = useState(""); const [viewOpen, setViewOpen] = useState(false); const [viewData, setViewData] = useState(null); @@ -56,6 +57,8 @@ export default function AppointmentPage() { currentPage, itemsPerPage, filterDate, + startDate, + endDate, searchText, ); setAppointments(res?.data || []); @@ -66,7 +69,7 @@ export default function AppointmentPage() { } finally { setLoading(false); } - }, [currentPage, itemsPerPage, filterDate, searchText]); + }, [currentPage, itemsPerPage, filterDate, startDate, endDate, searchText]); useEffect(() => { fetchAll(); @@ -116,39 +119,87 @@ export default function AppointmentPage() {

Appointments

-
- { - setSearchText(e.target.value); - setCurrentPage(1); - }} - className="w-[220px] text-base" - /> +
+
+ + { + setSearchText(e.target.value); + setCurrentPage(1); + }} + className="w-[220px] text-base" + /> +
- { - setFilterDate(e.target.value); - setCurrentPage(1); - }} - className="w-[160px] text-base" - /> +
+ + { + setFilterDate(e.target.value); + setCurrentPage(1); + }} + className="w-[160px] text-base" + disabled={!!startDate || !!endDate} + /> +
- +
+ + { + setStartDate(e.target.value); + setCurrentPage(1); + }} + className="w-[160px] text-base" + disabled={!!filterDate} + /> +
+ +
+ + { + setEndDate(e.target.value); + setCurrentPage(1); + }} + className="w-[160px] text-base" + disabled={!!filterDate} + /> +
+ +
+ + +