diff --git a/client/src/layouts/dashboard/config-navigation.jsx b/client/src/layouts/dashboard/config-navigation.jsx index 64bc0da..c97d7a2 100644 --- a/client/src/layouts/dashboard/config-navigation.jsx +++ b/client/src/layouts/dashboard/config-navigation.jsx @@ -39,11 +39,13 @@ const navConfig = [ title: 'Doctors', path: '/doctors', icon: icon('ic_user') - }, { + }, + { title: 'Upload Documents', path: '/upload-document', icon: icon('ic_disabled') - }, { + }, + { title: 'Medical History', path: '/medical-history', icon: icon('ic_disabled') @@ -52,6 +54,11 @@ const navConfig = [ title: 'Not found', path: '/404', icon: icon('ic_disabled') + }, + { + title: 'View Requests', + path: '/requests-list', + icon: icon('ic_disabled') } ]; diff --git a/client/src/pages/requests-list.jsx b/client/src/pages/requests-list.jsx new file mode 100644 index 0000000..27f3221 --- /dev/null +++ b/client/src/pages/requests-list.jsx @@ -0,0 +1,10 @@ +import { DisplayRequestsView } from 'src/sections/upload/displayRequests'; + +function RequestsListPage() { + return ( +
+ +
+ ); +} +export default RequestsListPage; \ No newline at end of file diff --git a/client/src/routes/sections.jsx b/client/src/routes/sections.jsx index 5bcde8b..3686b5b 100644 --- a/client/src/routes/sections.jsx +++ b/client/src/routes/sections.jsx @@ -14,7 +14,7 @@ export const RegisterPage = lazy(() => import('src/pages/register')); export const ProductsPage = lazy(() => import('src/pages/products')); export const Page404 = lazy(() => import('src/pages/page-not-found')); export const DoctorDocumentUploadPage = lazy(() => import('src/pages/doctor-document-upload')); - +export const RequestsListPage = lazy(() => import('src/pages/requests-list')); export const MedicalHistoryPage = lazy(() => import('src/pages/medical-history')); // ---------------------------------------------------------------------- @@ -35,13 +35,9 @@ export default function Router() { { path: 'products', element: }, { path: 'blog', element: }, { path: 'doctors', element: }, - { - path: '/upload-document', - element: - }, { - path: '/medical-history', - element: - } + { path: '/upload-document', element: }, + { path: '/medical-history', element: }, + { path: 'requests-list', element: }, ] }, { diff --git a/client/src/sections/upload/displayRequests.jsx b/client/src/sections/upload/displayRequests.jsx new file mode 100644 index 0000000..a079d94 --- /dev/null +++ b/client/src/sections/upload/displayRequests.jsx @@ -0,0 +1,190 @@ + +import React, { useEffect, useState } from 'react'; +import Modal from '@mui/material/Modal'; +import PDFViewer from './viewPDF'; +import ImageViewer from './viewImage.jsx'; +import IconButton from '@mui/material/IconButton'; +import Button from '@mui/material/Button' +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import ExpandLessIcon from '@mui/icons-material/ExpandLess'; +import { axiosInstance } from '../../utils/axiosInstance'; +import Typography from '@mui/material/Typography' +import Box from '@mui/material/Box'; + +const List = ({ field, array, doctorID }) => { + const [rows, setRows] = useState([]); + + useEffect(() => { + const newRows = array?.map((item, index) => { + let spitedFileName = String(item).split('.'); + let extension = spitedFileName[spitedFileName.length - 1]; + + return ( + + ); + }); + + setRows(newRows); + }, [array, doctorID, field]); + + return ( +
+ {rows} +
+ ); +}; + +const Row = ({ text, doctorID, field, extension }) => { + const [isExpanded, setIsExpanded] = useState(false); + const [isHovered, setIsHovered] = useState(false); + + const toggleExpand = () => { + setIsExpanded(!isExpanded); + }; + + const rowStyle = { + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + padding: '10px', + backgroundColor: isExpanded || isHovered ? '#e0f7fa' : 'transparent', + transition: 'background-color 0.3s', + cursor: 'pointer', + border: '1px solid #b2ebf2', + borderRadius: '5px', + marginBottom: '5px', + }; + + return ( +
+
setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + > +
{text}
+ + {isExpanded ? : } + +
+ {isExpanded && } +
+ ); +}; + +const AdditionalContent = ({ doctorID, text, field, extension }) => { + const [comp, setComp] = useState(

{text}

); + const [url, setUrl] = useState(`http://localhost:3000/upload/doctor/registration/${doctorID}/${field}/${text}`); + + useEffect(() => { + setUrl(`http://localhost:3000/upload/doctor/registration/${doctorID}/${field}/${text}`); + }, []) + + useEffect(() => { + console.log("----------", extension, text, "----------") + if (['pdf', 'jpg', 'jpeg', 'png'].includes(String(extension).toLowerCase())) { + setComp( + String(extension).toLowerCase() === 'pdf' + ? + : + ); + } + }, [extension, text]); + + const contentStyle = { + marginTop: '10px', + marginLeft: '20px', + border: '1px solid #b2ebf2', + borderRadius: '5px', + padding: '10px', + backgroundColor: '#e0f7fa', + }; + + return ( +
+ {comp} +
+ ); +}; + +const DisplayRequests = ({ doctorID }) => { + const [requests, setRequests] = useState({}); + + useEffect(() => { + const fetchData = async () => { + try { + const res = await axiosInstance.get(`/upload/doctor/registration/${doctorID}`); + setRequests(res.data.result); + } catch (err) { + console.error(err); + } + }; + fetchData(); + }, [doctorID]); + + const labelStyle = { + fontSize: '18px', + fontWeight: 'bold', + marginBottom: '5px', + }; + + return ( +
+
ID
+ + +
Licenses
+ + +
Degree
+ +
+ ); +}; + + + + +const DisplayRequestsView = ({ doctorID }) => { + const [isModalOpen, setIsModalOpen] = useState(false); + + const handleOpenModal = () => { + setIsModalOpen(true); + }; + + const handleCloseModal = () => { + setIsModalOpen(false); + }; + + return ( +
+ + + + + + Requests + + + + +
+ ); +}; +export { DisplayRequestsView }; diff --git a/client/src/sections/upload/viewImage.jsx b/client/src/sections/upload/viewImage.jsx index 2e9efe3..58e0034 100644 --- a/client/src/sections/upload/viewImage.jsx +++ b/client/src/sections/upload/viewImage.jsx @@ -1,5 +1,6 @@ function ImageViewer({ url }) { + console.log('Image URL:', url); // Log the URL return (
Health record diff --git a/server/src/routes/upload.route.ts b/server/src/routes/upload.route.ts index 63c8bac..1456b2b 100644 --- a/server/src/routes/upload.route.ts +++ b/server/src/routes/upload.route.ts @@ -6,15 +6,19 @@ import multer from 'multer'; import path from 'path'; import { isAuthenticated, isAuthorized } from '../middlewares'; import { medicalHistoryUpload , registrationUpload ,allowedRegistrationFields} from '../middlewares'; -import {saveMedicalHistory,removeMedicalHistory,saveRegistrationFiles,getMedicalHistoryURL,getMedicalHistory,getAllRequests} from '../services' +import {saveMedicalHistory,removeMedicalHistory,saveRegistrationFiles,getMedicalHistoryURL,getMedicalHistory,getAllRequests,getRequestFileUrl} from '../services' const uploadRouter = Router(); uploadRouter.use(isAuthenticated); uploadRouter.get("/patient/medicalHistory/:recordName", async (req, res) => { + const recordName: string = req.params["recordName"]; - console.log(recordName, "-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+") const fileUrl: any = await getMedicalHistoryURL({ recordName, _id: req.decoded.id }); + if (!fileUrl) + return res.status(StatusCodes.NOT_FOUND).send("File not found"); + res.status(200).sendFile(fileUrl!); + }); uploadRouter.delete("/patient/medicalHistory/:recordName", (req, res) => { controller(res)(removeMedicalHistory)(req.decoded.id,req.params.recordName); @@ -25,20 +29,28 @@ uploadRouter.get("/patient/medicalHistory/",async (req, res) => { }) uploadRouter.post("/patient/medicalHistory", medicalHistoryUpload.array("medicalHistory"), (req, res) => { const fileName = req.body.fileName; - console.log(fileName,"-+-+-+-+-+-"); controller(res)(saveMedicalHistory)( req.decoded.id,req.files,fileName); }); //------------------------------------------------------------------------------------------------------------------- +uploadRouter.get("/doctor/registration/:doctorID",async (req, res) => { + controller(res)(getAllRequests)(req.params.doctorID); +}) +uploadRouter.get("/doctor/registration/:doctorID/:type/:fileIDX",async (req, res) => { + const url = await getRequestFileUrl(req.params.doctorID, req.params.type, req.params.fileIDX); + // console.log(url," ----* -*-*-*-*-*-") + if (!url) + res.status(StatusCodes.NOT_FOUND).send("url not found"); + res.status(StatusCodes.OK).sendFile(url!); +}) + uploadRouter.use(isAuthorized("Doctor")); uploadRouter.post("/doctor/registration", registrationUpload.fields(allowedRegistrationFields as any[]),(req, res) => { controller(res)(saveRegistrationFiles)(req.decoded.id, req.files); }); -uploadRouter.get("/doctor/registration/",async (req, res) => { - controller(res)(getAllRequests)(req.decoded.id); -}) + uploadRouter.use((err: any, req: Request, res: Response) => { if (err instanceof multer.MulterError) { res.status(500).send(err.message); diff --git a/server/src/services/doctor.service.ts b/server/src/services/doctor.service.ts index 732763a..d9d335d 100644 --- a/server/src/services/doctor.service.ts +++ b/server/src/services/doctor.service.ts @@ -44,50 +44,8 @@ const getDoctors = async (query: any) => { return { result: doctors, status: StatusCodes.OK }; }; -const getPath = (files: any) => { - console.log(files) - - let results = []; - for (let i = 0; i < files.length; i++) { - const idx = files[i].path.indexOf('uploads'); - results.push(files[i].path.slice(idx)); - } -return results; - -} -const saveRegistrationFiles = async (doctorID: string, files: any) => { - - const IDFiles = files.ID; - const degreeFiles = files.medicalDegree; - const licensesFields = files.medicalLicenses; - - let IDPath: any = IDFiles ? (getPath(IDFiles)![0]) : undefined; - let degreePath: any[] = degreeFiles ? getPath(degreeFiles) : []; - let licensePath: any[] = licensesFields ? getPath(licensesFields) : []; - // Construct the updates object - let updates: any = { - ID: IDPath, - $push: { - degree: { $each: degreePath }, // Use $each for pushing multiple elements - licenses: { $each: licensePath } // Use $each for pushing multiple elements - } - }; - // Remove the 'ID' field if it doesn't exist - if (!IDPath) { - delete updates.ID; - } - console.log(updates, "------------"); - const results = await Request.findOneAndUpdate({ medicID: doctorID }, updates, { new: true }); - // const results = await Request.findOneAndUpdate({ medicID: doctorID }, updates, {new:true}); - console.log(results); - return { - result: results, - status: StatusCodes.OK, - message: "Registration Documents uploaded successfully" - } -} const viewAvailableAppointments = async (doctorID: string) => { const doctor = await Doctor.findById(doctorID); if (!doctor) throw new HttpError(StatusCodes.NOT_FOUND, 'Doctor not found'); @@ -192,4 +150,4 @@ const viewAvailableAppointments = async (doctorID: string) => { }; }; -export { getDoctors, getMyPatients, viewAvailableAppointments, saveRegistrationFiles }; \ No newline at end of file +export { getDoctors, getMyPatients, viewAvailableAppointments, }; \ No newline at end of file diff --git a/server/src/services/patient.service.ts b/server/src/services/patient.service.ts index 1d7da88..3dd80ba 100644 --- a/server/src/services/patient.service.ts +++ b/server/src/services/patient.service.ts @@ -111,14 +111,14 @@ const getMedicalHistory = async (patientID: String) => { } const resolveURL = (url: string) => { - console.log(url, "-----------"); + if (!url) + return null; const parentURL = path.dirname(__dirname); url = path.join(parentURL, url!); return url; } const getMedicalHistoryURL = async (body: any) => { let result = await Patient.findOne({ _id: body._id }).select("medicalHistory").lean(); - console.log(body,"++++++***-+-+-+-*****--*-*-*-*-") if (!result) throw new HttpError(StatusCodes.NOT_FOUND, "not found"); let records = result!["medicalHistory"]; diff --git a/server/src/services/request.service.ts b/server/src/services/request.service.ts index cd7cebf..d1980fe 100644 --- a/server/src/services/request.service.ts +++ b/server/src/services/request.service.ts @@ -1,8 +1,8 @@ import { Request } from "../models"; - - +import StatusCodes from 'http-status-codes'; +import path from 'path'; const getAllRequests = async (medicID: string) => { - const requests = await Request.find({medicID: medicID}); + const requests = await Request.findOne({medicID: medicID}); return { status: 200, message: "Requests retrieved successfully", @@ -10,5 +10,66 @@ const getAllRequests = async (medicID: string) => { }; } +const saveRegistrationFiles = async (doctorID: string, files: any) => { + + const IDFiles = files.ID; + const degreeFiles = files.medicalDegree; + const licensesFields = files.medicalLicenses; + + let IDPath: any = IDFiles ? (getPath(IDFiles)![0]) : undefined; + let degreePath: any[] = degreeFiles ? getPath(degreeFiles) : []; + let licensePath: any[] = licensesFields ? getPath(licensesFields) : []; + + let updates: any = { + ID: IDPath, + $push: { + degree: { $each: degreePath }, + licenses: { $each: licensePath } + } + }; + + if (!IDPath) { + delete updates.ID; + } + console.log(updates, "------------"); + const results = await Request.findOneAndUpdate({ medicID: doctorID }, updates, { new: true }); + console.log(results); + return { + result: results, + status: StatusCodes.OK, + message: "Registration Documents uploaded successfully" + } + +} +const getPath = (files: any) => { + console.log(files) + + let results = []; + for (let i = 0; i < files.length; i++) { + const idx = files[i].path.indexOf('uploads'); + results.push(files[i].path.slice(idx)); + } +return results; + +} +const resolveURL = (url: string) => { + if (!url) + return null; + const parentURL = path.dirname(__dirname); + url = path.join(parentURL, url!); + return url; +} +//licenses degree ID +const getRequestFileUrl = async (medicID: string, type:any, fileIDX: string)=>{ + const requests = await Request.findOne({ medicID: medicID }); + if (!requests) throw new Error("Requests not found"); + let fileUrl; + if (type === 'ID') + fileUrl = requests.ID; + else + fileUrl = (requests as any)[type][Number(fileIDX)]; + + return resolveURL(fileUrl); -export { getAllRequests }; \ No newline at end of file +}; +export { getAllRequests,getRequestFileUrl,saveRegistrationFiles }; \ No newline at end of file