diff --git a/backend/src/controllers/doctor.controller.js b/backend/src/controllers/doctor.controller.js index a7f6796..a7087a3 100644 --- a/backend/src/controllers/doctor.controller.js +++ b/backend/src/controllers/doctor.controller.js @@ -17,37 +17,35 @@ export const getAllDoctors = async (req, res) => { }); const formatted = doctors.map((doc, index) => { - const departmentIds = doc.departments.map( - (d) => d.department.departmentId, - ); - - let timings = []; - - doc.departments.forEach((d) => { - const t = d.timing; - - if (!t) return; - - if (t.monday) timings.push(`Monday ${t.monday}`); - if (t.tuesday) timings.push(`Tuesday ${t.tuesday}`); - if (t.wednesday) timings.push(`Wednesday ${t.wednesday}`); - if (t.thursday) timings.push(`Thursday ${t.thursday}`); - if (t.friday) timings.push(`Friday ${t.friday}`); - if (t.saturday) timings.push(`Saturday ${t.saturday}`); - if (t.sunday) timings.push(`Sunday ${t.sunday}`); - - if (t.additional) timings.push(t.additional); - }); - return { SL_NO: String(index + 1), - Doctor_ID: doc.doctorId, - Department_ID: departmentIds, - Name: doc.name, - Designation: doc.designation, - Working_Status: doc.workingStatus, - Qualification: doc.qualification, - Timing: timings.join(" & "), + doctorId: doc.doctorId, + name: doc.name, + designation: doc.designation, + workingStatus: doc.workingStatus, + qualification: doc.qualification, + + departments: doc.departments.map((d) => { + const t = d.timing || {}; + + const timingArray = [ + t.monday && `Monday ${t.monday}`, + t.tuesday && `Tuesday ${t.tuesday}`, + t.wednesday && `Wednesday ${t.wednesday}`, + t.thursday && `Thursday ${t.thursday}`, + t.friday && `Friday ${t.friday}`, + t.saturday && `Saturday ${t.saturday}`, + t.sunday && `Sunday ${t.sunday}`, + t.additional && t.additional, + ].filter(Boolean); + + return { + departmentId: d.department.departmentId, + departmentName: d.department.name, + + timing: timingArray.join(" & "), + }; + }), }; }); @@ -89,29 +87,17 @@ export const getDoctorByDoctorId = async (req, res) => { }); } - const departments = doctor.departments.map( - (d) => d.department.departmentId, - ); - - const timing = doctor.departments[0]?.timing ?? {}; - const response = { doctorId: doctor.doctorId, name: doctor.name, designation: doctor.designation, workingStatus: doctor.workingStatus, qualification: doctor.qualification, - departments, - timing: { - monday: timing?.monday ?? "", - tuesday: timing?.tuesday ?? "", - wednesday: timing?.wednesday ?? "", - thursday: timing?.thursday ?? "", - friday: timing?.friday ?? "", - saturday: timing?.saturday ?? "", - sunday: timing?.sunday ?? "", - additional: timing?.additional ?? "", - }, + departments: doctor.departments.map((d) => ({ + departmentId: d.department.departmentId, + departmentName: d.department.name, + timing: d.timing || {}, + })), }; res.status(200).json({ @@ -137,7 +123,6 @@ export const createDoctor = async (req, res) => { workingStatus, qualification, departments, - timing, } = req.body; const doctor = await prisma.doctor.create({ @@ -150,11 +135,13 @@ export const createDoctor = async (req, res) => { }, }); - for (const depId of departments) { + for (const dep of departments) { const department = await prisma.department.findUnique({ - where: {departmentId: depId}, + where: {departmentId: dep.departmentId}, }); + if (!department) continue; + const doctorDepartment = await prisma.doctorDepartment.create({ data: { doctorId: doctor.id, @@ -162,11 +149,11 @@ export const createDoctor = async (req, res) => { }, }); - if (timing) { + if (dep.timing) { await prisma.doctorTiming.create({ data: { doctorDepartmentId: doctorDepartment.id, - ...timing, + ...dep.timing, }, }); } @@ -189,21 +176,8 @@ export const createDoctor = async (req, res) => { export const updateDoctor = async (req, res) => { try { const {doctorId} = req.params; - const { - name, - designation, - workingStatus, - qualification, - departments, - timing, - } = req.body; - - if (!doctorId) { - return res.status(400).json({ - success: false, - message: "Doctor ID is required", - }); - } + const {name, designation, workingStatus, qualification, departments} = + req.body; const doctor = await prisma.doctor.findUnique({ where: {doctorId}, @@ -212,75 +186,61 @@ export const updateDoctor = async (req, res) => { if (!doctor) { return res.status(404).json({ success: false, - message: `Doctor with ID ${doctorId} not found`, + message: "Doctor not found", }); } - const updatedDoctor = await prisma.doctor.update({ + await prisma.doctor.update({ where: {id: doctor.id}, data: { - ...(name && {name}), - ...(designation && {designation}), - ...(workingStatus && {workingStatus}), - ...(qualification && {qualification}), + name, + designation, + workingStatus, + qualification, }, }); - if (departments) { - const doctorDepartments = await prisma.doctorDepartment.findMany({ - where: {doctorId: doctor.id}, + const oldRelations = await prisma.doctorDepartment.findMany({ + where: {doctorId: doctor.id}, + }); + + 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 department = await prisma.department.findUnique({ + where: {departmentId: dep.departmentId}, }); - for (const dd of doctorDepartments) { - await prisma.doctorTiming.deleteMany({ - where: {doctorDepartmentId: dd.id}, - }); - } + if (!department) continue; - await prisma.doctorDepartment.deleteMany({ - where: {doctorId: doctor.id}, + const doctorDepartment = await prisma.doctorDepartment.create({ + data: { + doctorId: doctor.id, + departmentId: department.id, + }, }); - for (const depId of departments) { - const department = await prisma.department.findUnique({ - where: {departmentId: depId}, - }); - if (!department) continue; - - const doctorDepartment = await prisma.doctorDepartment.create({ + if (dep.timing) { + await prisma.doctorTiming.create({ data: { - doctorId: doctor.id, - departmentId: department.id, + doctorDepartmentId: doctorDepartment.id, + ...dep.timing, }, }); - - if (timing) { - await prisma.doctorTiming.create({ - data: { - doctorDepartmentId: doctorDepartment.id, - ...timing, - }, - }); - } - } - } else if (timing) { - const doctorDepartments = await prisma.doctorDepartment.findMany({ - where: {doctorId: doctor.id}, - }); - - for (const dd of doctorDepartments) { - await prisma.doctorTiming.upsert({ - where: {doctorDepartmentId: dd.id}, - update: {...timing}, - create: {doctorDepartmentId: dd.id, ...timing}, - }); } } res.status(200).json({ success: true, - message: `Doctor ${doctorId} updated successfully`, - data: updatedDoctor, + message: "Doctor updated successfully", }); } catch (error) { console.error(error); @@ -403,6 +363,7 @@ export const getDoctorTimingById = async (req, res) => { include: { departments: { include: { + department: true, timing: true, }, }, @@ -416,23 +377,29 @@ export const getDoctorTimingById = async (req, res) => { }); } - let timing = {}; - - if (doctor.departments.length > 0) { - timing = doctor.departments[0].timing ?? {}; - } - const result = { - Doctor_ID: doctor.doctorId, - Doctor: doctor.name, - Monday: timing?.monday ?? "", - Tuesday: timing?.tuesday ?? "", - Wednesday: timing?.wednesday ?? "", - Thursday: timing?.thursday ?? "", - Friday: timing?.friday ?? "", - Saturday: timing?.saturday ?? "", - Sunday: timing?.sunday ?? "", - Additional: timing?.additional ?? "", + doctorId: doctor.doctorId, + doctorName: doctor.name, + + departments: doctor.departments.map((d) => { + const t = d.timing || {}; + + return { + departmentId: d.department.departmentId, + departmentName: d.department.name, + + timing: { + monday: t.monday || "", + tuesday: t.tuesday || "", + wednesday: t.wednesday || "", + thursday: t.thursday || "", + friday: t.friday || "", + saturday: t.saturday || "", + sunday: t.sunday || "", + additional: t.additional || "", + }, + }; + }), }; res.status(200).json({ diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index ce13fff..de0ab13 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -3,7 +3,6 @@ import {BrowserRouter, Routes, Route, Navigate} from "react-router-dom"; import Login from "@/pages/Login"; import DashboardLayout from "./layouts/DashboardLayout"; -import Blog from "./pages/Blog"; // import ProtectedRoute from "./components/ProtectedRoutes/ProtectedRoutes"; @@ -12,6 +11,7 @@ import PublicRoute from "./auth/PublicRoute"; import {AuthProvider} from "./context/AuthContext"; import Department from "./pages/Department"; import Doctor from "./pages/Doctor"; +import Blog from "./pages/Blog"; export default function App() { return ( @@ -24,9 +24,9 @@ export default function App() { }> }> - } /> } /> } /> + } /> diff --git a/frontend/src/api/doctor.ts b/frontend/src/api/doctor.ts index f9ab808..18c0014 100644 --- a/frontend/src/api/doctor.ts +++ b/frontend/src/api/doctor.ts @@ -6,17 +6,20 @@ export interface Doctor { designation?: string; workingStatus?: string; qualification?: string; - departments: string[]; - timing: { - monday?: string; - tuesday?: string; - wednesday?: string; - thursday?: string; - friday?: string; - saturday?: string; - sunday?: string; - additional?: string; - }; + + departments: { + departmentId: string; + timing?: { + monday?: string; + tuesday?: string; + wednesday?: string; + thursday?: string; + friday?: string; + saturday?: string; + sunday?: string; + additional?: string; + }; + }[]; } export const getDoctorsApi = async () => { diff --git a/frontend/src/components/layout/Sidebar.tsx b/frontend/src/components/layout/Sidebar.tsx index 573bc08..365ed31 100644 --- a/frontend/src/components/layout/Sidebar.tsx +++ b/frontend/src/components/layout/Sidebar.tsx @@ -16,8 +16,8 @@ export default function Sidebar() { path: "/doctor", }, { - name: "Subjects", - path: "/subjects", + name: "Blog", + path: "/blog", }, ]; diff --git a/frontend/src/components/ui/scroll-area.tsx b/frontend/src/components/ui/scroll-area.tsx new file mode 100644 index 0000000..f49b0a8 --- /dev/null +++ b/frontend/src/components/ui/scroll-area.tsx @@ -0,0 +1,53 @@ +import * as React from "react" +import { ScrollArea as ScrollAreaPrimitive } from "radix-ui" + +import { cn } from "@/lib/utils" + +function ScrollArea({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + + {children} + + + + + ) +} + +function ScrollBar({ + className, + orientation = "vertical", + ...props +}: React.ComponentProps) { + return ( + + + + ) +} + +export { ScrollArea, ScrollBar } diff --git a/frontend/src/pages/Doctor.tsx b/frontend/src/pages/Doctor.tsx index 053110a..57c4a56 100644 --- a/frontend/src/pages/Doctor.tsx +++ b/frontend/src/pages/Doctor.tsx @@ -1,6 +1,4 @@ import {useState, useEffect, useCallback} from "react"; -import {AxiosError} from "axios"; - import { getDoctorsApi, createDoctorApi, @@ -19,6 +17,7 @@ import { TableHeader, TableRow, } from "@/components/ui/table"; +import {ScrollArea} from "@/components/ui/scroll-area"; import {Card, CardContent, CardHeader, CardTitle} from "@/components/ui/card"; import {Button} from "@/components/ui/button"; @@ -30,13 +29,16 @@ import { DialogTitle, DialogFooter, } from "@/components/ui/dialog"; -import {Popover, PopoverContent, PopoverTrigger} from "@/components/ui/popover"; -import {Command, CommandGroup, CommandItem} from "@/components/ui/command"; -import {Check} from "lucide-react"; +import {Popover, PopoverContent, PopoverTrigger} from "@/components/ui/popover"; +import { + Command, + CommandGroup, + CommandItem, + CommandInput, +} from "@/components/ui/command"; import {Input} from "@/components/ui/input"; import {Loader2, Plus, Pencil, Trash} from "lucide-react"; -import {log} from "console"; interface Department { departmentId: string; @@ -46,11 +48,9 @@ interface Department { export default function DoctorPage() { const [doctors, setDoctors] = useState([]); const [departments, setDepartments] = useState([]); - const [loading, setLoading] = useState(true); const [openModal, setOpenModal] = useState(false); const [editing, setEditing] = useState(null); - const [depOpen, setDepOpen] = useState(false); const [search, setSearch] = useState(""); const [form, setForm] = useState({ @@ -60,7 +60,6 @@ export default function DoctorPage() { workingStatus: "", qualification: "", departments: [], - timing: {}, }); const fetchAll = useCallback(async () => { @@ -89,20 +88,43 @@ export default function DoctorPage() { } function handleDepartmentChange(depId: string) { - const exists = form.departments.includes(depId); + const exists = form.departments.find((d: any) => d.departmentId === depId); - setForm({ - ...form, - departments: exists - ? form.departments.filter((d: string) => d !== depId) - : [...form.departments, depId], - }); + if (exists) { + setForm({ + ...form, + departments: form.departments.filter( + (d: any) => d.departmentId !== depId, + ), + }); + } else { + setForm({ + ...form, + departments: [ + ...form.departments, + { + departmentId: depId, + timing: {}, + }, + ], + }); + } } - function handleTimingChange(day: string, value: string) { + function handleTimingChange(depId: string, day: string, value: string) { setForm({ ...form, - timing: {...form.timing, [day]: value}, + departments: form.departments.map((d: any) => + d.departmentId === depId + ? { + ...d, + timing: { + ...d.timing, + [day]: value, + }, + } + : d, + ), }); } @@ -115,7 +137,6 @@ export default function DoctorPage() { workingStatus: "", qualification: "", departments: [], - timing: {}, }); setOpenModal(true); } @@ -124,29 +145,22 @@ export default function DoctorPage() { setEditing(doc); try { - const timingRes = await getDoctorTimingApi(doc.Doctor_ID); + const timingRes = await getDoctorTimingApi(doc.doctorId); - const t = timingRes?.data || {}; + const timingData = timingRes?.data?.departments || []; - const formattedTiming = { - sunday: t.Sunday || "", - monday: t.Monday || "", - tuesday: t.Tuesday || "", - wednesday: t.Wednesday || "", - thursday: t.Thursday || "", - friday: t.Friday || "", - saturday: t.Saturday || "", - additional: t.Additional || "", - }; + const mappedDepartments = timingData.map((d: any) => ({ + departmentId: d.departmentId, + timing: d.timing || {}, + })); setForm({ - doctorId: doc.Doctor_ID, - name: doc.Name, - designation: doc.Designation, - workingStatus: doc.workingStatus || doc.Working_Status || "", - qualification: doc.Qualification, - departments: doc.Department_ID || [], - timing: formattedTiming, + doctorId: doc.doctorId, + name: doc.name, + designation: doc.designation, + workingStatus: doc.workingStatus, + qualification: doc.qualification, + departments: mappedDepartments, }); setOpenModal(true); @@ -157,21 +171,17 @@ export default function DoctorPage() { async function handleSubmit() { try { - const cleanTiming: any = {}; - - Object.keys(form.timing).forEach((day) => { - if (form.timing[day]) { - cleanTiming[day] = form.timing[day]; - } - }); - const payload = { - ...form, - timing: cleanTiming, + doctorId: form.doctorId, + name: form.name, + designation: form.designation, + workingStatus: form.workingStatus, + qualification: form.qualification, + departments: form.departments, }; if (editing) { - await updateDoctorApi(editing.Doctor_ID, payload); + await updateDoctorApi(editing.doctorId, payload); } else { await createDoctorApi(payload); } @@ -185,7 +195,6 @@ export default function DoctorPage() { async function handleDelete(id: string) { if (!confirm("Delete doctor?")) return; - await deleteDoctorApi(id); fetchAll(); } @@ -231,21 +240,25 @@ export default function DoctorPage() { ) : ( doctors.map((doc) => ( - - {doc.Doctor_ID} + + {doc.doctorId} + {doc.name} + {doc.designation} + {doc.workingStatus} + {doc.qualification} - {doc.Name} + + {doc.departments + ?.map((d: any) => d.departmentName) + .join(", ")} + - {doc.Designation} - - {doc.Working_Status} - - {doc.Qualification} - - {doc.Department_ID?.join(", ")} - - -
{doc.Timing}
+ + {doc.departments?.map((d: any) => ( +
+ {d.departmentName}: {d.timing} +
+ ))}
@@ -260,7 +273,7 @@ export default function DoctorPage() { @@ -275,14 +288,13 @@ export default function DoctorPage() { {/* MODAL */} - - + {editing ? "Edit Doctor" : "Add Doctor"} -
+
- + - {/* Departments MULTI SELECT */} - + {/* Departments */}
-

Departments

+

Departments

- - + -
- setSearch(e.target.value)} - /> -
+ - - {departments - .filter((d) => - d.name.toLowerCase().includes(search.toLowerCase()), - ) - .map((dep) => { - const selected = form.departments.includes( - dep.departmentId, - ); + + {departments.map((dep) => { + const selected = form.departments.some( + (d: any) => d.departmentId === dep.departmentId, + ); - return ( - - handleDepartmentChange(dep.departmentId) - } - className="tw-flex tw-justify-between" - > - {dep.name} - - {selected && ( - - ✔ - - )} - - ); - })} + return ( + + handleDepartmentChange(dep.departmentId) + } + > + {dep.name} + {selected && } + + ); + })}
- handleTimingChange("sunday", e.target.value)} - /> - handleTimingChange("monday", e.target.value)} - /> + {form.departments.map((dep: any) => { + const depName = departments.find( + (d) => d.departmentId === dep.departmentId, + )?.name; - handleTimingChange("tuesday", e.target.value)} - /> + return ( +
+

{depName}

- handleTimingChange("wednesday", e.target.value)} - /> - - handleTimingChange("thursday", e.target.value)} - /> - - handleTimingChange("friday", e.target.value)} - /> - - handleTimingChange("saturday", e.target.value)} - /> - handleTimingChange("additional", e.target.value)} - /> + {[ + "monday", + "tuesday", + "wednesday", + "thursday", + "friday", + "saturday", + "sunday", + "additional", + ].map((day) => ( + + handleTimingChange( + dep.departmentId, + day, + e.target.value, + ) + } + /> + ))} +
+ ); + })}
-