USER
i am giving doctor appointment system mern project from youtube now i need to understand file fully so i will give each file explain it
I'd be happy to help you understand each file in your MERN (MongoDB, Express, React, Node.js) project for a doctor appointment system. Please go ahead and share the first file, and I'll break it down and explain its contents and purpose in the project.
You can share the file name and its contents, and I'll provide a detailed explanation. If there's any specific part of the file you're struggling to understand, feel free to point that out as well.
Let's get started!
const mongoose = require("mongoose");
const colors = require("colors");
const connectDB = async () => {
try {
await mongoose.connect(process.env.MONGO_URL);
console.log(Mongodb connected ${mongoose.connection.host}.bgGreen.white);
} catch (error) {
console.log(Mongodb Server Issue ${error}.bgRed.white);
}
};
module.exports = connectDB;
This file is setting up a connection to a MongoDB database using Mongoose, a popular ODM (Object Data Modeling) library for MongoDB in Node.js. Here's a breakdown of the code:
Lines 1-2:
const mongoose = require("mongoose"); imports the Mongoose library.
const colors = require("colors"); imports the Colors library, which is used to add colors to console logs.
Lines 4-11:
const connectDB = async () => { ... } defines an asynchronous function named connectDB.
try { ... } catch (error) { ... } is a try-catch block that attempts to connect to the database and handles any errors that occur.
Inside the try block:
await mongoose.connect(process.env.MONGO_URL); connects to the MongoDB database using the URL stored in the MONGO_URL environment variable.
console.log(Mongodb connected ${mongoose.connection.host}.bgGreen.white); logs a success message to the console, including the host name of the connected database. The .bgGreen.white part adds green background and white text colors to the log message using the Colors library.
Inside the catch block:
console.log(Mongodb Server Issue ${error}.bgRed.white); logs an error message to the console, including the error details. The .bgRed.white part adds red background and white text colors to the log message using the Colors library.
Line 12:
module.exports = connectDB; exports the connectDB function as a module, making it available for use in other parts of the application.
In summary, this file sets up a function to connect to a MongoDB database using Mongoose and exports it as a module. The function logs a success message with the connected host name or an error message with details if the connection fails.
const userModel = require("../models/userModels");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const doctorModel = require("../models/doctorModel");
const appointmentModel = require("../models/appointmentModel");
const moment = require("moment");
//register callback
const registerController = async (req, res) => {
try {
const exisitingUser = await userModel.findOne({ email: req.body.email });
if (exisitingUser) {
return res
.status(200)
.send({ message: "User Already Exist", success: false });
}
const password = req.body.password;
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
req.body.password = hashedPassword;
const newUser = new userModel(req.body);
await newUser.save();
res.status(201).send({ message: "Register Sucessfully", success: true });
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
message: Register Controller ${error.message},
});
}
};
// login callback
const loginController = async (req, res) => {
try {
const user = await userModel.findOne({ email: req.body.email });
if (!user) {
return res
.status(200)
.send({ message: "user not found", success: false });
}
const isMatch = await bcrypt.compare(req.body.password, user.password);
if (!isMatch) {
return res
.status(200)
.send({ message: "Invlid EMail or Password", success: false });
}
const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, {
expiresIn: "1d",
});
res.status(200).send({ message: "Login Success", success: true, token });
} catch (error) {
console.log(error);
res.status(500).send({ message: Error in Login CTRL ${error.message} });
}
};
const authController = async (req, res) => {
try {
const user = await userModel.findById({ _id: req.body.userId });
user.password = undefined;
if (!user) {
return res.status(200).send({
message: "user not found",
success: false,
});
} else {
res.status(200).send({
success: true,
data: user,
});
}
} catch (error) {
console.log(error);
res.status(500).send({
message: "auth error",
success: false,
error,
});
}
};
// APpply DOctor CTRL
const applyDoctorController = async (req, res) => {
try {
const newDoctor = await doctorModel({ ...req.body, status: "pending" });
await newDoctor.save();
const adminUser = await userModel.findOne({ isAdmin: true });
const notifcation = adminUser.notifcation;
notifcation.push({
type: "apply-doctor-request",
message: ${newDoctor.firstName} ${newDoctor.lastName} Has Applied For A Doctor Account,
data: {
doctorId: newDoctor._id,
name: newDoctor.firstName + " " + newDoctor.lastName,
onClickPath: "/admin/docotrs",
},
});
await userModel.findByIdAndUpdate(adminUser._id, { notifcation });
res.status(201).send({
success: true,
message: "Doctor Account Applied SUccessfully",
});
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
error,
message: "Error WHile Applying For Doctotr",
});
}
};
//notification ctrl
const getAllNotificationController = async (req, res) => {
try {
const user = await userModel.findOne({ _id: req.body.userId });
const seennotification = user.seennotification;
const notifcation = user.notifcation;
seennotification.push(...notifcation);
user.notifcation = [];
user.seennotification = notifcation;
const updatedUser = await user.save();
res.status(200).send({
success: true,
message: "all notification marked as read",
data: updatedUser,
});
} catch (error) {
console.log(error);
res.status(500).send({
message: "Error in notification",
success: false,
error,
});
}
};
// delete notifications
const deleteAllNotificationController = async (req, res) => {
try {
const user = await userModel.findOne({ _id: req.body.userId });
user.notifcation = [];
user.seennotification = [];
const updatedUser = await user.save();
updatedUser.password = undefined;
res.status(200).send({
success: true,
message: "Notifications Deleted successfully",
data: updatedUser,
});
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
message: "unable to delete all notifications",
error,
});
}
};
//GET ALL DOC
const getAllDocotrsController = async (req, res) => {
try {
const doctors = await doctorModel.find({ status: "approved" });
res.status(200).send({
success: true,
message: "Docots Lists Fetched Successfully",
data: doctors,
});
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
error,
message: "Errro WHile Fetching DOcotr",
});
}
};
//BOOK APPOINTMENT
const bookeAppointmnetController = async (req, res) => {
try {
req.body.date = moment(req.body.date, "DD-MM-YYYY").toISOString();
req.body.time = moment(req.body.time, "HH:mm").toISOString();
req.body.status = "pending";
const newAppointment = new appointmentModel(req.body);
await newAppointment.save();
const user = await userModel.findOne({ _id: req.body.doctorInfo.userId });
user.notifcation.push({
type: "New-appointment-request",
message: A nEw Appointment Request from ${req.body.userInfo.name},
onCLickPath: "/user/appointments",
});
await user.save();
res.status(200).send({
success: true,
message: "Appointment Book succesfully",
});
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
error,
message: "Error While Booking Appointment",
});
}
};
// booking bookingAvailabilityController
const bookingAvailabilityController = async (req, res) => {
try {
const date = moment(req.body.date, "DD-MM-YY").toISOString();
const fromTime = moment(req.body.time, "HH:mm")
.subtract(1, "hours")
.toISOString();
const toTime = moment(req.body.time, "HH:mm").add(1, "hours").toISOString();
const doctorId = req.body.doctorId;
const appointments = await appointmentModel.find({
doctorId,
date,
time: {
$gte: fromTime,
$lte: toTime,
},
});
if (appointments.length > 0) {
return res.status(200).send({
message: "Appointments not Availibale at this time",
success: true,
});
} else {
return res.status(200).send({
success: true,
message: "Appointments available",
});
}
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
error,
message: "Error In Booking",
});
}
};
const userAppointmentsController = async (req, res) => {
try {
const appointments = await appointmentModel.find({
userId: req.body.userId,
});
res.status(200).send({
success: true,
message: "Users Appointments Fetch SUccessfully",
data: appointments,
});
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
error,
message: "Error In User Appointments",
});
}
};
module.exports = {
loginController,
registerController,
authController,
applyDoctorController,
getAllNotificationController,
deleteAllNotificationController,
getAllDocotrsController,
bookeAppointmnetController,
bookingAvailabilityController,
userAppointmentsController,
};
This file contains various controller functions for handling user authentication, doctor applications, notifications, appointments, and more. Here's a brief overview of each controller:
registerController: Handles user registration, checks if the user already exists, hashes the password, and saves the new user.
loginController: Handles user login, checks if the user exists, compares the provided password with the hashed password, and generates a JWT token upon successful login.
authController: Authenticates a user by finding them in the database using their ID and returns their data (excluding the password).
applyDoctorController: Handles doctor applications, creates a new doctor document with a "pending" status, and notifies the admin.
getAllNotificationController: Retrieves all notifications for a user, marks them as seen, and returns the updated user data.
deleteAllNotificationController: Deletes all notifications for a user.
getAllDocotrsController: Retrieves a list of approved doctors.
bookeAppointmnetController: Books an appointment, saves the appointment, and notifies the doctor.
bookingAvailabilityController: Checks if an appointment is available at a given time.
userAppointmentsController: Retrieves a list of appointments for a user.
Each controller function uses async/await syntax, try-catch blocks for error handling, and returns responses with success messages, data, or error messages. The file exports all these controller functions for use in other parts of the application.
const appointmentModel = require("../models/appointmentModel");
const doctorModel = require("../models/doctorModel");
const userModel = require("../models/userModels");
const getDoctorInfoController = async (req, res) => {
try {
const doctor = await doctorModel.findOne({ userId: req.body.userId });
res.status(200).send({
success: true,
message: "doctor data fetch success",
data: doctor,
});
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
error,
message: "Error in Fetching Doctor Details",
});
}
};
// update doc profile
const updateProfileController = async (req, res) => {
try {
const doctor = await doctorModel.findOneAndUpdate(
{ userId: req.body.userId },
req.body
);
res.status(201).send({
success: true,
message: "Doctor Profile Updated",
data: doctor,
});
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
message: "Doctor Profile Update issue",
error,
});
}
};
//get single docotor
const getDoctorByIdController = async (req, res) => {
try {
const doctor = await doctorModel.findOne({ _id: req.body.doctorId });
res.status(200).send({
success: true,
message: "Sigle Doc Info Fetched",
data: doctor,
});
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
error,
message: "Erro in Single docot info",
});
}
};
const doctorAppointmentsController = async (req, res) => {
try {
const doctor = await doctorModel.findOne({ userId: req.body.userId });
const appointments = await appointmentModel.find({
doctorId: doctor._id,
});
res.status(200).send({
success: true,
message: "Doctor Appointments fetch Successfully",
data: appointments,
});
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
error,
message: "Error in Doc Appointments",
});
}
};
const updateStatusController = async (req, res) => {
try {
const { appointmentsId, status } = req.body;
const appointments = await appointmentModel.findByIdAndUpdate(
appointmentsId,
{ status }
);
const user = await userModel.findOne({ _id: appointments.userId });
const notifcation = user.notifcation;
notifcation.push({
type: "status-updated",
message: your appointment has been updated ${status},
onCLickPath: "/doctor-appointments",
});
await user.save();
res.status(200).send({
success: true,
message: "Appointment Status Updated",
});
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
error,
message: "Error In Update Status",
});
}
};
module.exports = {
getDoctorInfoController,
updateProfileController,
getDoctorByIdController,
doctorAppointmentsController,
updateStatusController,
};
This file contains five controller functions for managing doctor-related operations:
getDoctorInfoController: Retrieves a doctor's information based on their user ID.
updateProfileController: Updates a doctor's profile information.
getDoctorByIdController: Retrieves a single doctor's information based on their ID.
doctorAppointmentsController: Retrieves a list of appointments for a specific doctor.
updateStatusController: Updates the status of an appointment and notifies the user.
Each controller function uses async/await syntax, try-catch blocks for error handling, and returns responses with success messages, data, or error messages. The file exports all these controller functions for use in other parts of the application.
Here's a summary of the functionality:
Doctor information management (retrieval and update)
Appointment management (retrieval and status update)
User notification system (for appointment status updates)
These controllers interact with the doctorModel, appointmentModel, and userModel to perform database operations.
const doctorModel = require("../models/doctorModel");
const userModel = require("../models/userModels");
const getAllUsersController = async (req, res) => {
try {
const users = await userModel.find({});
res.status(200).send({
success: true,
message: "users data list",
data: users,
});
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
message: "erorr while fetching users",
error,
});
}
};
const getAllDoctorsController = async (req, res) => {
try {
const doctors = await doctorModel.find({});
res.status(200).send({
success: true,
message: "Doctors Data list",
data: doctors,
});
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
message: "error while getting doctors data",
error,
});
}
};
// doctor account status
const changeAccountStatusController = async (req, res) => {
try {
const { doctorId, status } = req.body;
const doctor = await doctorModel.findByIdAndUpdate(doctorId, { status });
const user = await userModel.findOne({ _id: doctor.userId });
const notifcation = user.notifcation;
notifcation.push({
type: "doctor-account-request-updated",
message: Your Doctor Account Request Has ${status} ,
onClickPath: "/notification",
});
user.isDoctor = status === "approved" ? true : false;
await user.save();
res.status(201).send({
success: true,
message: "Account Status Updated",
data: doctor,
});
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
message: "Eror in Account Status",
error,
});
}
};
module.exports = {
getAllDoctorsController,
getAllUsersController,
changeAccountStatusController,
};
This file contains three controller functions for managing users and doctors:
getAllUsersController: Retrieves a list of all users.
getAllDoctorsController: Retrieves a list of all doctors.
changeAccountStatusController: Updates the status of a doctor's account (approved, pending, rejected) and notifies the user.
Each controller function uses async/await syntax, try-catch blocks for error handling, and returns responses with success messages, data, or error messages. The file exports all these controller functions for use in other parts of the application.
Here's a summary of the functionality:
User management (retrieval of all users)
Doctor management (retrieval of all doctors, update of account status)
User notification system (for doctor account status updates)
These controllers interact with the doctorModel and userModel to perform database operations.
Note that the changeAccountStatusController function not only updates the doctor's account status but also:
Updates the user's isDoctor field based on the new status
Adds a notification to the user's notifications array
Saves the updated user document
const JWT = require("jsonwebtoken");
module.exports = async (req, res, next) => {
try {
const token = req.headers["authorization"].split(" ")[1];
JWT.verify(token, process.env.JWT_SECRET, (err, decode) => {
if (err) {
return res.status(200).send({
message: "Auth Fialed",
success: false,
});
} else {
req.body.userId = decode.id;
next();
}
});
} catch (error) {
console.log(error);
res.status(401).send({
message: "Auth Failed",
success: false,
});
}
};
This is a middleware function for authenticating JSON Web Tokens (JWT) in an Express.js application. Here's a breakdown of the code:
Purpose:
Verify the authenticity of incoming requests by checking the JWT token in the Authorization header.
If the token is valid, extract the user's ID from the token and attach it to the req.body object.
If the token is invalid or missing, return an error response.
Code explanation:
const token = req.headers["authorization"].split(" ")[1];:
Extract the JWT token from the Authorization header. The token is expected to be in the format Bearer <token>, so we split the string by space and take the second part ([1]).
JWT.verify(token, process.env.JWT_SECRET, (err, decode) => { ... });:
Verify the token using the jsonwebtoken library. The JWT_SECRET is used as the secret key for verification.
If the token is valid, the decode object will contain the payload (including the user's ID).
if (err) { ... }:
If an error occurs during verification (e.g., invalid token), return an error response with a 200 status code (note: this should probably be a 401 status code instead).
req.body.userId = decode.id;:
If the token is valid, extract the user's ID from the decode object and attach it to the req.body object.
next();:
Call the next middleware function in the stack.
catch (error) { ... }:
Catch any errors that occur during the middleware execution and return an error response with a 401 status code.
In summary, this middleware function checks the JWT token in incoming requests, verifies its authenticity, and extracts the user's ID if valid. If the token is invalid or missing, it returns an error response.
import { createSlice } from "@reduxjs/toolkit";
export const alertSlice = createSlice({
name: "alerts",
initialState: {
loading: false,
},
reducers: {
showLoading: (state) => {
state.loading = true;
},
hideLoading: (state) => {
state.loading = false;
},
},
});
export const { showLoading, hideLoading } = alertSlice.actions;
import { createSlice } from "@reduxjs/toolkit";
export const userSlice = createSlice({
name: "user",
initialState: {
user: null,
},
reducers: {
setUser: (state, action) => {
state.user = action.payload;
},
},
});
export const { setUser } = userSlice.actions;
import { configureStore } from "@reduxjs/toolkit";
import { alertSlice } from "./features/alertSlice";
import { userSlice } from "./features/userSlice";
export default configureStore({
reducer: {
alerts: alertSlice.reducer,
user: userSlice.reducer,
},
});
This code is setting up a Redux store using the @reduxjs/toolkit library. Here's a breakdown of what's happening:
alertSlice.js
Creates a Redux slice named "alerts" with an initial state of { loading: false }.
Defines two reducers:
showLoading: sets loading to true.
hideLoading: sets loading to false.
Exports the showLoading and hideLoading actions.
userSlice.js
Creates a Redux slice named "user" with an initial state of { user: null }.
Defines one reducer:
setUser: sets user to the payload of the action.
Exports the setUser action.
store.js
Imports the alertSlice and userSlice reducers.
Configures the Redux store using configureStore.
Combines the reducers into a single object with keys "alerts" and "user".
Exports the configured store.
In summary, this code sets up a Redux store with two slices: "alerts" and "user". The "alerts" slice manages a loading state, while the "user" slice manages a user state. The store is configured to combine these slices into a single state object.
import React from "react";
const Spinner = () => {
return (
<div class="d-flex justify-content-center spinner">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
);
};
export default Spinner;
import React from "react";
import { Navigate } from "react-router-dom";
export default function PublicRoute({ children }) {
if (localStorage.getItem("token")) {
return <Navigate to="/" />;
} else {
return children;
}
}
import React, { useEffect } from "react";
import { Navigate } from "react-router-dom";
import axios from "axios";
import { useSelector, useDispatch } from "react-redux";
import { hideLoading, showLoading } from "../redux/features/alertSlice";
import { setUser } from "../redux/features/userSlice";
export default function ProtectedRoute({ children }) {
const dispatch = useDispatch();
const { user } = useSelector((state) => state.user);
//get user
//eslint-disable-next-line
const getUser = async () => {
try {
dispatch(showLoading());
const res = await axios.post(
"/api/v1/user/getUserData",
{ token: localStorage.getItem("token") },
{
headers: {
Authorization: Bearer ${localStorage.getItem("token")},
},
}
);
dispatch(hideLoading());
if (res.data.success) {
dispatch(setUser(res.data.data));
} else {
localStorage.clear();
<Navigate to="/login" />;
}
} catch (error) {
localStorage.clear();
dispatch(hideLoading());
console.log(error);
}
};
useEffect(() => {
if (!user) {
getUser();
}
}, [user, getUser]);
if (localStorage.getItem("token")) {
return children;
} else {
return <Navigate to="/login" />;
}
}
import React, { useEffect } from "react";
import { Navigate } from "react-router-dom";
import axios from "axios";
import { useSelector, useDispatch } from "react-redux";
import { hideLoading, showLoading } from "../redux/features/alertSlice";
import { setUser } from "../redux/features/userSlice";
export default function ProtectedRoute({ children }) {
const dispatch = useDispatch();
const { user } = useSelector((state) => state.user);
//get user
//eslint-disable-next-line
const getUser = async () => {
try {
dispatch(showLoading());
const res = await axios.post(
"/api/v1/user/getUserData",
{ token: localStorage.getItem("token") },
{
headers: {
Authorization: Bearer ${localStorage.getItem("token")},
},
}
);
dispatch(hideLoading());
if (res.data.success) {
dispatch(setUser(res.data.data));
} else {
localStorage.clear();
<Navigate to="/login" />;
}
} catch (error) {
localStorage.clear();
dispatch(hideLoading());
console.log(error);
}
};
useEffect(() => {
if (!user) {
getUser();
}
}, [user, getUser]);
if (localStorage.getItem("token")) {
return children;
} else {
return <Navigate to="/login" />;
}
}
This code is for a React application using Redux for state management and React Router for navigation. Here's a breakdown of the components:
Spinner.js
A simple loading spinner component using Bootstrap classes.
PublicRoute.js
A route component that checks if a token is present in local storage.
If a token is present, it redirects to the root route ("/").
If no token is present, it renders the child components.
ProtectedRoute.js
A route component that checks if a token is present in local storage and if the user data is present in the Redux store.
If a token is present and user data is not present, it calls the getUser function to fetch user data from the API.
If user data is present, it renders the child components.
If no token is present, it redirects to the login route ("/login").
The getUser function:
Dispatches the showLoading action to display a loading spinner.
Makes an API call to fetch user data using the token.
Dispatches the hideLoading action to hide the loading spinner.
If the API call is successful, it dispatches the setUser action to store the user data in the Redux store.
If the API call fails or the token is invalid, it clears local storage and redirects to the login route.
Note that there are two identical ProtectedRoute components. The second one can be removed.
import React from "react";
import Layout from "./../components/Layout";
import { message, Tabs } from "antd";
import { useSelector, useDispatch } from "react-redux";
import { showLoading, hideLoading } from "../redux/features/alertSlice";
import { useNavigate } from "react-router-dom";
import axios from "axios";
const NotificationPage = () => {
const dispatch = useDispatch();
const navigate = useNavigate();
const { user } = useSelector((state) => state.user);
// handle read notification
const handleMarkAllRead = async () => {
try {
dispatch(showLoading());
const res = await axios.post(
"/api/v1/user/get-all-notification",
{
userId: user._id,
},
{
headers: {
Authorization: Bearer ${localStorage.getItem("token")},
},
}
);
dispatch(hideLoading());
if (res.data.success) {
message.success(res.data.message);
} else {
message.error(res.data.message);
}
} catch (error) {
dispatch(hideLoading());
console.log(error);
message.error("somthing went wrong");
}
};
// delete notifications
const handleDeleteAllRead = async () => {
try {
dispatch(showLoading());
const res = await axios.post(
"/api/v1/user/delete-all-notification",
{ userId: user._id },
{
headers: {
Authorization: Bearer ${localStorage.getItem("token")},
},
}
);
dispatch(hideLoading());
if (res.data.success) {
message.success(res.data.message);
} else {
message.error(res.data.message);
}
} catch (error) {
dispatch(hideLoading());
console.log(error);
message.error("Somthing Went Wrong In Ntifications");
}
};
return (
<Layout>
<h4 className="p-3 text-center">Notification Page</h4>
<Tabs>
<Tabs.TabPane tab="unRead" key={0}>
<div className="d-flex justify-content-end">
<h4 className="p-2" onClick={handleMarkAllRead}>
Mark All Read
</h4>
</div>
{user?.notifcation.map((notificationMgs) => (
<div className="card" style={{ cursor: "pointer" }}>
<div
className="card-text"
onClick={() => navigate(notificationMgs.onClickPath)}
>
{notificationMgs.message}
</div>
</div>
))}
</Tabs.TabPane>
<Tabs.TabPane tab="Read" key={1}>
<div className="d-flex justify-content-end">
<h4
className="p-2 text-primary"
style={{ cursor: "pointer" }}
onClick={handleDeleteAllRead}
>
Delete All Read
</h4>
</div>
{user?.seennotification.map((notificationMgs) => (
<div className="card" style={{ cursor: "pointer" }}>
<div
className="card-text"
onClick={() => navigate(notificationMgs.onClickPath)}
>
{notificationMgs.message}
</div>
</div>
))}
</Tabs.TabPane>
</Tabs>
</Layout>
);
};
export default NotificationPage;
This is a React component for a notification page. Here's a breakdown of the code:
NotificationPage.js
Imports necessary components and hooks from React, Ant Design, Redux, and React Router.
Defines the NotificationPage component, which:
Uses the useDispatch and useSelector hooks to access the Redux store and dispatch actions.
Uses the useNavigate hook to navigate to different routes.
Defines two functions:
handleMarkAllRead: marks all notifications as read by making an API call to /api/v1/user/get-all-notification.
handleDeleteAllRead: deletes all read notifications by making an API call to /api/v1/user/delete-all-notification.
Renders a layout with a tabs component (using Ant Design's Tabs component).
The tabs component has two tabs: "Unread" and "Read".
The "Unread" tab displays a list of unread notifications, with a "Mark All Read" button that calls handleMarkAllRead when clicked.
The "Read" tab displays a list of read notifications, with a "Delete All Read" button that calls handleDeleteAllRead when clicked.
Each notification is displayed as a card with a clickable message that navigates to the notification's onClickPath.
Note that the code assumes that the user's notifications are stored in the Redux store under state.user.notifcation and state.user.seennotification.
import React, { useState, useEffect } from "react";
import Layout from "./../../components/Layout";
import axios from "axios";
import { message, Table } from "antd";
const Doctors = () => {
const [doctors, setDoctors] = useState([]);
//getUsers
const getDoctors = async () => {
try {
const res = await axios.get("/api/v1/admin/getAllDoctors", {
headers: {
Authorization: Bearer ${localStorage.getItem("token")},
},
});
if (res.data.success) {
setDoctors(res.data.data);
}
} catch (error) {
console.log(error);
}
};
// handle account
const handleAccountStatus = async (record, status) => {
try {
const res = await axios.post(
"/api/v1/admin/changeAccountStatus",
{ doctorId: record._id, userId: record.userId, status: status },
{
headers: {
Authorization: Bearer ${localStorage.getItem("token")},
},
}
);
if (res.data.success) {
message.success(res.data.message);
window.location.reload();
}
} catch (error) {
message.error("Something Went Wrong");
}
};
useEffect(() => {
getDoctors();
}, []);
const columns = [
{
title: "Name",
dataIndex: "name",
render: (text, record) => (
<span>
{record.firstName} {record.lastName}
</span>
),
},
{
title: "Status",
dataIndex: "status",
},
{
title: "phone",
dataIndex: "phone",
},
{
title: "Actions",
dataIndex: "actions",
render: (text, record) => (
<div className="d-flex">
{record.status === "pending" ? (
<button
className="btn btn-success"
onClick={() => handleAccountStatus(record, "approved")}
>
Approve
</button>
) : (
<button className="btn btn-danger">Reject</button>
)}
</div>
),
},
];
return (
<Layout>
<h1 className="text-center m-3">All Doctors</h1>
<Table columns={columns} dataSource={doctors} />
</Layout>
);
};
export default Doctors;
This is a React component that displays a list of doctors and allows administrators to manage their account status. Here's a breakdown of the code:
Doctors.js
Imports necessary components and hooks from React, Ant Design, and Axios.
Defines the Doctors component, which:
Uses the useState hook to store the list of doctors in the component's state.
Defines two functions:
getDoctors: fetches the list of doctors from the API and updates the component's state.
handleAccountStatus: updates the account status of a doctor and refreshes the page.
Uses the useEffect hook to fetch the list of doctors when the component mounts.
Defines the columns for the table using Ant Design's Table component.
Renders a layout with a table that displays the list of doctors and allows administrators to approve or reject their account status.
The table has four columns:
Name: displays the doctor's full name
Status: displays the doctor's account status
Phone: displays the doctor's phone number
Actions: displays buttons to approve or reject the doctor's account status
When the administrator clicks the "Approve" or "Reject" button, the handleAccountStatus function is called, which updates the doctor's account status and refreshes the page.
import React, { useEffect, useState } from "react";
import Layout from "./../../components/Layout";
import axios from "axios";
import { Table } from "antd";
const Users = () => {
const [users, setUsers] = useState([]);
//getUsers
const getUsers = async () => {
try {
const res = await axios.get("/api/v1/admin/getAllUsers", {
headers: {
Authorization: Bearer ${localStorage.getItem("token")},
},
});
if (res.data.success) {
setUsers(res.data.data);
}
} catch (error) {
console.log(error);
}
};
useEffect(() => {
getUsers();
}, []);
// antD table col
const columns = [
{
title: "Name",
dataIndex: "name",
},
{
title: "Email",
dataIndex: "email",
},
{
title: "Doctor",
dataIndex: "isDoctor",
render: (text, record) => <span>{record.isDoctor ? "Yes" : "No"}</span>,
},
{
title: "Actions",
dataIndex: "actions",
render: (text, record) => (
<div className="d-flex">
<button className="btn btn-danger">Block</button>
</div>
),
},
];
return (
<Layout>
<h1 className="text-center m-2">Users List</h1>
<Table columns={columns} dataSource={users} />
</Layout>
);
};
export default Users;
This is a React component that displays a list of users and allows administrators to block them. Here's a breakdown of the code:
Users.js
Imports necessary components and hooks from React, Ant Design, and Axios.
Defines the Users component, which:
Uses the useState hook to store the list of users in the component's state.
Defines a function getUsers to fetch the list of users from the API and update the component's state.
Uses the useEffect hook to fetch the list of users when the component mounts.
Defines the columns for the table using Ant Design's Table component.
Renders a layout with a table that displays the list of users and allows administrators to block them.
The table has four columns:
Name: displays the user's name
Email: displays the user's email
Doctor: displays whether the user is a doctor or not
Actions: displays a button to block the user
Note that the "Block" button is currently not functional, as it does not call any function when clicked. You would need to add a function to handle the blocking of a user and update the component's state accordingly.
import React, { useState, useEffect } from "react";
import Layout from "./../../components/Layout";
import axios from "axios";
import moment from "moment";
import { message, Table } from "antd";
const DoctorAppointments = () => {
const [appointments, setAppointments] = useState([]);
const getAppointments = async () => {
try {
const res = await axios.get("/api/v1/doctor//doctor-appointments", {
headers: {
Authorization: Bearer ${localStorage.getItem("token")},
},
});
if (res.data.success) {
setAppointments(res.data.data);
}
} catch (error) {
console.log(error);
}
};
useEffect(() => {
getAppointments();
}, []);
const handleStatus = async (record, status) => {
try {
const res = await axios.post(
"/api/v1/doctor/update-status",
{ appointmentsId: record._id, status },
{
headers: {
Authorization: Bearer ${localStorage.getItem("token")},
},
}
);
if (res.data.success) {
message.success(res.data.message);
getAppointments();
}
} catch (error) {
console.log(error);
message.error("Something Went Wrong");
}
};
const columns = [
{
title: "ID",
dataIndex: "_id",
},
{
title: "Date & Time",
dataIndex: "date",
render: (text, record) => (
<span>
{moment(record.date).format("DD-MM-YYYY")}
{moment(record.time).format("HH:mm")}
</span>
),
},
{
title: "Status",
dataIndex: "status",
},
{
title: "Actions",
dataIndex: "actions",
render: (text, record) => (
<div className="d-flex">
{record.status === "pending" && (
<div className="d-flex">
<button
className="btn btn-success"
onClick={() => handleStatus(record, "approved")}
>
Approved
</button>
<button
className="btn btn-danger ms-2"
onClick={() => handleStatus(record, "reject")}
>
Reject
</button>
</div>
)}
</div>
),
},
];
return (
<Layout>
<h1>Appoinmtnets Lists</h1>
<Table columns={columns} dataSource={appointments} />
</Layout>
);
};
export default DoctorAppointments;
This is a React component that displays a list of appointments for a doctor and allows them to update the status of each appointment. Here's a breakdown of the code:
DoctorAppointments.js
Imports necessary components and hooks from React, Ant Design, Axios, and Moment.js.
Defines the DoctorAppointments component, which:
Uses the useState hook to store the list of appointments in the component's state.
Defines a function getAppointments to fetch the list of appointments from the API and update the component's state.
Uses the useEffect hook to fetch the list of appointments when the component mounts.
Defines a function handleStatus to update the status of an appointment and refresh the list of appointments.
Defines the columns for the table using Ant Design's Table component.
Renders a layout with a table that displays the list of appointments and allows the doctor to update the status of each appointment.
The table has four columns:
ID: displays the appointment ID
Date & Time: displays the appointment date and time, formatted using Moment.js
Status: displays the appointment status
Actions: displays buttons to approve or reject the appointment, depending on its current status
When the doctor clicks the "Approved" or "Reject" button, the handleStatus function is called, which updates the appointment status and refreshes the list of appointments.
import React, { useEffect, useState } from "react";
import Layout from "./../../components/Layout";
import axios from "axios";
import { useParams, useNavigate } from "react-router-dom";
import { Col, Form, Input, Row, TimePicker, message } from "antd";
import { useSelector, useDispatch } from "react-redux";
import { showLoading, hideLoading } from "../../redux/features/alertSlice";
import moment from "moment";
const Profile = () => {
const { user } = useSelector((state) => state.user);
const [doctor, setDoctor] = useState(null);
const dispatch = useDispatch();
const navigate = useNavigate();
const params = useParams();
// update doc ==========
//handle form
const handleFinish = async (values) => {
try {
dispatch(showLoading());
const res = await axios.post(
"/api/v1/doctor/updateProfile",
{
...values,
userId: user._id,
timings: [
moment(values.timings[0]).format("HH:mm"),
moment(values.timings[1]).format("HH:mm"),
],
},
{
headers: {
Authorization: Bearer ${localStorage.getItem("token")},
},
}
);
dispatch(hideLoading());
if (res.data.success) {
message.success(res.data.message);
navigate("/");
} else {
message.error(res.data.success);
}
} catch (error) {
dispatch(hideLoading());
console.log(error);
message.error("Somthing Went Wrrong ");
}
};
// update doc ==========
//getDOc Details
const getDoctorInfo = async () => {
try {
const res = await axios.post(
"/api/v1/doctor/getDoctorInfo",
{ userId: params.id },
{
headers: {
Authorization: Bearer ${localStorage.getItem("token")},
},
}
);
if (res.data.success) {
setDoctor(res.data.data);
}
} catch (error) {
console.log(error);
}
};
useEffect(() => {
getDoctorInfo();
//eslint-disable-next-line
}, []);
return (
<Layout>
<h1>Manage Profile</h1>
{doctor && (
<Form
layout="vertical"
onFinish={handleFinish}
className="m-3"
initialValues={{
...doctor,
timings: [
moment(doctor.timings[0], "HH:mm"),
moment(doctor.timings[1], "HH:mm"),
],
}}
>
<h4 className="">Personal Details : </h4>
<Row gutter={20}>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="First Name"
name="firstName"
required
rules={[{ required: true }]}
>
<Input type="text" placeholder="your first name" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="Last Name"
name="lastName"
required
rules={[{ required: true }]}
>
<Input type="text" placeholder="your last name" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="Phone No"
name="phone"
required
rules={[{ required: true }]}
>
<Input type="text" placeholder="your contact no" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="Email"
name="email"
required
rules={[{ required: true }]}
>
<Input type="email" placeholder="your email address" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item label="Website" name="website">
<Input type="text" placeholder="your website" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="Address"
name="address"
required
rules={[{ required: true }]}
>
<Input type="text" placeholder="your clinic address" />
</Form.Item>
</Col>
</Row>
<h4>Professional Details :</h4>
<Row gutter={20}>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="Specialization"
name="specialization"
required
rules={[{ required: true }]}
>
<Input type="text" placeholder="your specialization" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="Experience"
name="experience"
required
rules={[{ required: true }]}
>
<Input type="text" placeholder="your experience" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="Fees Per Cunsaltation"
name="feesPerCunsaltation"
required
rules={[{ required: true }]}
>
<Input type="text" placeholder="your contact no" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item label="Timings" name="timings" required>
<TimePicker.RangePicker format="HH:mm" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}></Col>
<Col xs={24} md={24} lg={8}>
<button className="btn btn-primary form-btn" type="submit">
Update
</button>
</Col>
</Row>
</Form>
)}
</Layout>
);
};
export default Profile;
No notes for now.
This code is a React component that allows a doctor to manage their profile. It fetches the doctor's information from the API and displays a form to update their personal and professional details. The form includes fields for name, phone number, email, website, address, specialization, experience, fees per consultation, and timings. When the form is submitted, it sends a request to the API to update the doctor's profile.
Here's a breakdown of the code:
Profile.js
Imports necessary components and hooks from React, Ant Design, Axios, and React Router.
Defines the Profile component, which:
Uses the useState hook to store the doctor's information in the component's state.
Uses the useDispatch and useSelector hooks to access the Redux store and dispatch actions.
Defines a function handleFinish to handle the form submission and update the doctor's profile.
Defines a function getDoctorInfo to fetch the doctor's information from the API.
Uses the useEffect hook to fetch the doctor's information when the component mounts.
Renders a layout with a form that displays the doctor's information and allows them to update their profile.
Note that this code assumes that the API endpoints /api/v1/doctor/updateProfile and /api/v1/doctor/getDoctorInfo are defined and functional.
import React from "react";
import Layout from "./../components/Layout";
import { Col, Form, Input, Row, TimePicker, message } from "antd";
import { useSelector, useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import { showLoading, hideLoading } from "../redux/features/alertSlice";
import axios from "axios";
import moment from "moment";
const ApplyDoctor = () => {
const { user } = useSelector((state) => state.user);
const dispatch = useDispatch();
const navigate = useNavigate();
//handle form
const handleFinish = async (values) => {
try {
dispatch(showLoading());
const res = await axios.post(
"/api/v1/user/apply-doctor",
{
...values,
userId: user._id,
timings: [
moment(values.timings[0]).format("HH:mm"),
moment(values.timings[1]).format("HH:mm"),
],
},
{
headers: {
Authorization: Bearer ${localStorage.getItem("token")},
},
}
);
dispatch(hideLoading());
if (res.data.success) {
message.success(res.data.message);
navigate("/");
} else {
message.error(res.data.message);
}
} catch (error) {
dispatch(hideLoading());
console.log(error);
message.error("Somthing Went Wrrong ");
}
};
return (
<Layout>
<h1 className="text-center">Apply Doctor</h1>
<Form layout="vertical" onFinish={handleFinish} className="m-3">
<h4 className="">Personal Details : </h4>
<Row gutter={20}>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="First Name"
name="firstName"
required
rules={[{ required: true }]}
>
<Input type="text" placeholder="your first name" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="Last Name"
name="lastName"
required
rules={[{ required: true }]}
>
<Input type="text" placeholder="your last name" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="Phone No"
name="phone"
required
rules={[{ required: true }]}
>
<Input type="text" placeholder="your contact no" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="Email"
name="email"
required
rules={[{ required: true }]}
>
<Input type="email" placeholder="your email address" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item label="Website" name="website">
<Input type="text" placeholder="your website" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="Address"
name="address"
required
rules={[{ required: true }]}
>
<Input type="text" placeholder="your clinic address" />
</Form.Item>
</Col>
</Row>
<h4>Professional Details :</h4>
<Row gutter={20}>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="Specialization"
name="specialization"
required
rules={[{ required: true }]}
>
<Input type="text" placeholder="your specialization" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="Experience"
name="experience"
required
rules={[{ required: true }]}
>
<Input type="text" placeholder="your experience" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item
label="Fees Per Cunsaltation"
name="feesPerCunsaltation"
required
rules={[{ required: true }]}
>
<Input type="text" placeholder="your contact no" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}>
<Form.Item label="Timings" name="timings" required>
<TimePicker.RangePicker format="HH:mm" />
</Form.Item>
</Col>
<Col xs={24} md={24} lg={8}></Col>
<Col xs={24} md={24} lg={8}>
<button className="btn btn-primary form-btn" type="submit">
Submit
</button>
</Col>
</Row>
</Form>
</Layout>
);
};
export default ApplyDoctor;
It looks like you've got a React component that allows users to apply to become doctors. Here's a breakdown of the code:
ApplyDoctor.js
Imports necessary components and hooks from React, Ant Design, Redux, and React Router.
Defines the ApplyDoctor component, which:
Uses the useSelector hook to access the user's information from the Redux store.
Uses the useDispatch hook to dispatch actions to the Redux store.
Uses the useNavigate hook to navigate to different routes.
Defines a function handleFinish to handle the form submission and send a request to the API to apply to become a doctor.
Renders a layout with a form that collects personal and professional details from the user.
The form includes fields for:
Personal details: first name, last name, phone number, email, website, and address
Professional details: specialization, experience, fees per consultation, and timings
When the form is submitted, the handleFinish function is called, which sends a request to the API to apply to become a doctor. If the response is successful, it displays a success message and navigates to the root route. If there's an error, it displays an error message.
Note that this code assumes that the API endpoint /api/v1/user/apply-doctor is defined and functional.
import React, { useState, useEffect } from "react";
import axios from "axios";
import Layout from "./../components/Layout";
import moment from "moment";
import { Table } from "antd";
const Appointments = () => {
const [appointments, setAppointments] = useState([]);
const getAppointments = async () => {
try {
const res = await axios.get("/api/v1/user/user-appointments", {
headers: {
Authorization: Bearer ${localStorage.getItem("token")},
},
});
if (res.data.success) {
setAppointments(res.data.data);
}
} catch (error) {
console.log(error);
}
};
useEffect(() => {
getAppointments();
}, []);
const columns = [
{
title: "ID",
dataIndex: "_id",
},
// {
// title: "Name",
// dataIndex: "name",
// render: (text, record) => (
// <span>
// {record.doctorInfo.firstName} {record.doctorInfo.lastName}
// </span>
// ),
// },
// {
// title: "Phone",
// dataIndex: "phone",
// render: (text, record) => <span>{record.doctorInfo.phone}</span>,
// },
{
title: "Date & Time",
dataIndex: "date",
render: (text, record) => (
<span>
{moment(record.date).format("DD-MM-YYYY")}
{moment(record.time).format("HH:mm")}
</span>
),
},
{
title: "Status",
dataIndex: "status",
},
];
return (
<Layout>
<h1>Appoinmtnets Lists</h1>
<Table columns={columns} dataSource={appointments} />
</Layout>
);
};
export default Appointments;
This is a React component that displays a list of appointments for a user. Here's a breakdown of the code:
Appointments.js
Imports necessary components and hooks from React, Axios, and Ant Design.
Defines the Appointments component, which:
Uses the useState hook to store the list of appointments in the component's state.
Defines a function getAppointments to fetch the list of appointments from the API and update the component's state.
Uses the useEffect hook to fetch the list of appointments when the component mounts.
Defines the columns for the table using Ant Design's Table component.
Renders a layout with a table that displays the list of appointments.
The table has four columns:
ID: displays the appointment ID
Date & Time: displays the appointment date and time, formatted using Moment.js
Status: displays the appointment status
Note that the name and phone columns are currently commented out, but they could be used to display the doctor's name and phone number if needed.
Also, the API endpoint /api/v1/user/user-appointments is assumed to be defined and functional, and it should return a list of appointments for the user.
import React, { useState, useEffect } from "react";
import Layout from "../components/Layout";
import { useParams } from "react-router-dom";
import axios from "axios";
import { DatePicker, message, TimePicker } from "antd";
import moment from "moment";
import { useDispatch, useSelector } from "react-redux";
import { showLoading, hideLoading } from "../redux/features/alertSlice";
const BookingPage = () => {
const { user } = useSelector((state) => state.user);
const params = useParams();
const [doctors, setDoctors] = useState([]);
const [date, setDate] = useState("");
const [time, setTime] = useState();
const [isAvailable, setIsAvailable] = useState(false);
const dispatch = useDispatch();
// login user data
const getUserData = async () => {
try {
const res = await axios.post(
"/api/v1/doctor/getDoctorById",
{ doctorId: params.doctorId },
{
headers: {
Authorization: "Bearer " + localStorage.getItem("token"),
},
}
);
if (res.data.success) {
setDoctors(res.data.data);
}
} catch (error) {
console.log(error);
}
};
// ============ handle availiblity
const handleAvailability = async () => {
try {
dispatch(showLoading());
const res = await axios.post(
"/api/v1/user/booking-availbility",
{ doctorId: params.doctorId, date, time },
{
headers: {
Authorization: Bearer ${localStorage.getItem("token")},
},
}
);
dispatch(hideLoading());
if (res.data.success) {
setIsAvailable(true);
console.log(isAvailable);
message.success(res.data.message);
} else {
message.error(res.data.message);
}
} catch (error) {
dispatch(hideLoading());
console.log(error);
}
};
// =============== booking func
const handleBooking = async () => {
try {
setIsAvailable(true);
if (!date && !time) {
return alert("Date & Time Required");
}
dispatch(showLoading());
const res = await axios.post(
"/api/v1/user/book-appointment",
{
doctorId: params.doctorId,
userId: user._id,
doctorInfo: doctors,
userInfo: user,
date: date,
time: time,
},
{
headers: {
Authorization: Bearer ${localStorage.getItem("token")},
},
}
);
dispatch(hideLoading());
if (res.data.success) {
message.success(res.data.message);
}
} catch (error) {
dispatch(hideLoading());
console.log(error);
}
};
useEffect(() => {
getUserData();
//eslint-disable-next-line
}, []);
return (
<Layout>
<h3>Booking Page</h3>
<div className="container m-2">
{doctors && (
<div>
<h4>
Dr.{doctors.firstName} {doctors.lastName}
</h4>
<h4>Fees : {doctors.feesPerCunsaltation}</h4>
<h4>
Timings : {doctors.timings && doctors.timings[0]} -{" "}
{doctors.timings && doctors.timings[1]}{" "}
</h4>
<div className="d-flex flex-column w-50">
<DatePicker
aria-required={"true"}
className="m-2"
format="DD-MM-YYYY"
onChange={(value) => {
setDate(moment(value).format("DD-MM-YYYY"));
}}
/>
<TimePicker
aria-required={"true"}
format="HH:mm"
className="mt-3"
onChange={(value) => {
setTime(moment(value).format("HH:mm"));
}}
/>
<button
className="btn btn-primary mt-2"
onClick={handleAvailability}
>
Check Availability
</button>
<button className="btn btn-dark mt-2" onClick={handleBooking}>
Book Now
</button>
</div>
</div>
)}
</div>
</Layout>
);
};
export default BookingPage;
This is a React component that allows users to book an appointment with a doctor. Here's a breakdown of the code:
BookingPage.js
Imports necessary components and hooks from React, Axios, Ant Design, and React Router.
Defines the BookingPage component, which:
Uses the useState hook to store the doctor's information, date, time, and availability in the component's state.
Uses the useDispatch and useSelector hooks to access the Redux store and dispatch actions.
Defines three functions:
getUserData to fetch the doctor's information from the API.
handleAvailability to check the availability of the doctor for a given date and time.
handleBooking to book an appointment with the doctor.
Uses the useEffect hook to fetch the doctor's information when the component mounts.
Renders a layout with a container that displays the doctor's information, a date picker, a time picker, and two buttons to check availability and book an appointment.
The component uses the following APIs:
/api/v1/doctor/getDoctorById to fetch the doctor's information.
/api/v1/user/booking-availbility to check the availability of the doctor.
/api/v1/user/book-appointment to book an appointment with the doctor.
Note that the component assumes that the API endpoints are defined and functional, and that the Redux store is set up to manage the user's information and the loading state.
from all these code give summary of what we are doing in such a way it can be told in interview in detail
Here's a summary of the code in a way that can be explained in detail in an interview:
Project Overview
We are building a doctor appointment booking system using React, Redux, and Ant Design. The system allows users to view doctor profiles, book appointments, and manage their bookings.
Components
Doctor Profile: This component displays a doctor's profile information, including their name, specialization, experience, and fees. It also allows doctors to update their profile information.
Appointment Booking: This component allows users to book an appointment with a doctor. It displays the doctor's availability and allows users to select a date and time for the appointment.
Appointment Management: This component displays a user's booked appointments and allows them to cancel or reschedule appointments.
Features
User Authentication: Users can log in and log out of the system using a token-based authentication system.
Doctor Profile Management: Doctors can update their profile information, including their name, specialization, experience, and fees.
Appointment Booking: Users can book an appointment with a doctor by selecting a date and time from the doctor's availability.
Appointment Management: Users can view their booked appointments and cancel or reschedule appointments.
Availability Checking: The system checks the doctor's availability before allowing a user to book an appointment.
Technical Details
Frontend: The frontend is built using React, Redux, and Ant Design.
Backend: The backend is built using Node.js and Express.js.
Database: The database is built using MongoDB.
APIs: The system uses RESTful APIs to communicate between the frontend and backend.
Authentication: The system uses token-based authentication to authenticate users.
Interview Explanation
In an interview, you can explain the project by starting with the project overview and then diving into the details of each component and feature. You can explain the technical details, including the frontend, backend, database, APIs, and authentication.
For example, you can say:
"In this project, we built a doctor appointment booking system using React, Redux, and Ant Design. The system allows users to view doctor profiles, book appointments, and manage their bookings. We used token-based authentication to authenticate users and RESTful APIs to communicate between the frontend and backend. We also used MongoDB as our database.
"The Doctor Profile component displays a doctor's profile information and allows doctors to update their profile information. The Appointment Booking component allows users to book an appointment with a doctor by selecting a date and time from the doctor's availability. The Appointment Management component displays a user's booked appointments and allows them to cancel or reschedule appointments.
"We used Redux to manage the state of the application and Ant Design to create a consistent user interface. We also used Node.js and Express.js to build the backend API."
This explanation provides a high-level overview of the project and its features, as well as technical details about the implementation.
from all the codes in the chat above give all important syntax which needs to be remembered or will be asked code in an tech interview
Here are the important syntax and code snippets that may be asked in a tech interview based on the codes provided:
React
useState hook: const [state, setState] = useState(initialState);
useEffect hook: useEffect(() => { /* code / }, [dependencies]);
useDispatch and useSelector hooks: const dispatch = useDispatch(); const state = useSelector((state) => state);
JSX syntax: <div> { / code / } </div>
React component structure: function Component() { return <div> / code / </div>; }
Redux
Action creators: const action = { type: 'ACTION_TYPE', payload: data };
Reducer function: const reducer = (state = initialState, action) => { switch (action.type) { / code / } };
Store creation: const store = createStore(reducer, initialState);
Dispatching actions: store.dispatch(action);
Axios
Making API requests: axios.get(url, { headers: { / headers / } });
Handling API responses: axios.get(url).then((response) => { / code / });
Ant Design
Importing Ant Design components: import { Button, Form, Input } from 'antd';
Using Ant Design components: <Button type="primary">Click me</Button>
JavaScript
Arrow functions: const func = (params) => { / code / };
Object destructuring: const { prop1, prop2 } = obj;
Spread operator: const newObj = { ...oldObj, newProp: 'value' };
Async/await syntax: async function func() { const data = await axios.get(url); }
Other
Token-based authentication: localStorage.getItem('token');
API endpoint structure: /api/v1/resource
MongoDB schema structure: const schema = new mongoose.Schema({ / fields */ });
These syntax and code snippets are commonly used in React, Redux, and Ant Design applications, and may be asked in a tech interview to assess your knowledge and understanding of these technologies.
give story of the technology stack where used and for what purpose for this application
Here's a story about the technology stack used for this application:
Once upon a time, a team of developers wanted to build a doctor appointment booking system that would allow patients to easily find and book appointments with doctors. They knew they needed a robust and scalable technology stack to handle the complexity of the application.
First, they chose React as the frontend framework because of its popularity, flexibility, and large community of developers. They wanted to build a fast and responsive user interface that would provide a great user experience.
Next, they added Redux to manage the state of the application. They needed a way to handle complex state changes and ensure that the application remained consistent and predictable. Redux provided a robust solution for state management.
Then, they selected Ant Design as the UI library because of its comprehensive set of components and consistent design language. They wanted to build a visually appealing and consistent interface that would make it easy for patients to navigate and book appointments.
For the backend, they chose Node.js and Express.js because of their lightweight and flexible nature. They wanted to build a fast and scalable API that could handle a large number of requests.
To store data, they chose MongoDB because of its flexible schema and scalability. They needed a database that could handle large amounts of data and provide fast query performance.
To handle API requests, they used Axios because of its simplicity and flexibility. They wanted a library that would make it easy to send and receive data from the backend API.
Finally, they implemented token-based authentication using JSON Web Tokens (JWT) to ensure secure authentication and authorization. They wanted to protect patient data and ensure that only authorized users could access the application.
Throughout the development process, the team used Git for version control and collaborated on the project using GitHub. They also used various other tools and libraries to support the development process, such as Webpack, Babel, and ESLint.
In the end, the team built a robust and scalable doctor appointment booking system that provided a great user experience and met the needs of patients and doctors alike. The technology stack they chose played a crucial role in the success of the project, and they were able to deliver a high-quality application on time.
Based on the video titles, here are the steps done in the Doctor Appointment MERN Stack App project:
Step 1-5: Project Setup and User Authentication
Project setup (video 1)
Node.js MVC server setup (video 2)
Creating React app and code cleanup (video 3)
Routing and login/register form setup (video 4)
Database connection and user model routes controller setup (video 5)
Step 6-8: User Registration and Login
Complete user registration (video 6)
Login user with JWT token (video 7)
Authorization with JWT (video 8)
Step 9-12: React Redux Toolkit and Private Routes
React Redux Toolkit setup (video 9)
Private public routes setup (video 10)
Layout setup (video 11)
Getting user details (video 12)
Step 13-18: Doctor Model and API
Doctor model form setup (video 13)
Doctor API and testing with form (video 14)
Admin notification setup (video 15)
Delete notifications setup (video 16)
Admin control pages setup (video 17)
Users and doctors list setup (video 18)
Step 19-24: Doctor Approval and Booking
Admin approving doctor setup (video 19)
Get doctor profile setup (video 20)
Update profile setup (video 21)
Get doctor lists setup (video 22)
Booking page setup (video 23)
Book appointments setup (video 24)
Step 25-28: Availability Check and Project Completion
Check availability setup (video 25)
Check availability setup (video 26)
User appointments setup (video 27)
Project completion (video 28) these are the steps followed in the project how to explain it to interviwer along with the above code info give interleaved info to tell to interviewer for 10 min
Here's an explanation of the project that you can use to explain to an interviewer for 10 minutes, interleaved with the code info:
Introduction (1 minute)
Hi, I worked on a Doctor Appointment MERN Stack App project, where I built a full-stack application using React, Node.js, Express.js, and MongoDB.
The application allows patients to book appointments with doctors and doctors to manage their profiles and appointments.
Project Setup and User Authentication (1.5 minutes)
First, I set up the project structure and created a Node.js MVC server (video 1-2).
I then created a React app and set up routing and login/register forms (video 3-4).
I connected to the database and set up user model routes and controllers (video 5).
I used JWT tokens for authentication and authorization (video 6-8).
React Redux Toolkit and Private Routes (1.5 minutes)
Next, I set up React Redux Toolkit and created private and public routes (video 9-10).
I created a layout component and got user details using Redux (video 11-12).
Doctor Model and API (2 minutes)
I then created a doctor model and API, and tested it with a form (video 13-14).
I set up admin notifications and delete notifications (video 15-16).
I created admin control pages and lists of users and doctors (video 17-18).
Doctor Approval and Booking (2 minutes)
After that, I set up admin approval for doctors and got doctor profiles (video 19-20).
I updated doctor profiles and got lists of doctors (video 21-22).
I created a booking page and booked appointments (video 23-24).
Availability Check and Project Completion (1 minute)
Finally, I checked availability and set up user appointments (video 25-27).
I completed the project and ensured everything was working as expected (video 28).
Code Explanation (1 minute)
Throughout the project, I used various code snippets, such as:
React hooks like useState and useEffect.
Redux actions and reducers.
Node.js and Express.js for the backend API.
MongoDB for data storage.
JWT tokens for authentication and authorization.
This explanation should give a good overview of the project and the technologies used, and can be delivered within 10 minutes.
give overall diagram to explain the flow of working
Here is an overall diagram to explain the flow of working of the Doctor Appointment MERN Stack App:
+---------------+
| Patient |
+---------------+
|
|
v
+---------------+
| Login/Register |
+---------------+
|
|
v
+---------------+
| User Auth |
| (JWT Token) |
+---------------+
|
|
v
+---------------+
| React App |
| (Redux Toolkit) |
+---------------+
|
|
v
+---------------+
| Node.js API |
| (Express.js) |
+---------------+
|
|
v
+---------------+
| MongoDB |
| (Data Storage) |
+---------------+
|
|
v
+---------------+
| Doctor Profile |
| (Approval, Booking) |
+---------------+
|
|
v
+---------------+
| Appointment Booking |
| (Availability Check) |
+---------------+
|
|
v
+---------------+
| User Appointments |
| (List, Cancel, Reschedule) |
+---------------+
This diagram shows the flow of working of the application, from patient login/register to user appointments. It includes the following components:
Patient: The user who wants to book an appointment.
Login/Register: The patient logs in or registers to access the application.
User Auth: The patient is authenticated using JWT tokens.
React App: The patient interacts with the React application, which uses Redux Toolkit for state management.
Node.js API: The React application communicates with the Node.js API, which uses Express.js as the framework.
MongoDB: The Node.js API stores and retrieves data from MongoDB.
Doctor Profile: The doctor's profile is managed, including approval and booking.
Appointment Booking: The patient books an appointment, which includes availability checking.
User Appointments: The patient can view, cancel, and reschedule their appointments.
This diagram should give a high-level overview of the application's flow and components.
what is the seperate use of mongodb and redux here
MongoDB is used as the database management system to store and retrieve data for the application. It is used to store:
User data (patient and doctor information)
Appointment data (booking information, availability, etc.)
Doctor profile data (doctor information, availability, etc.)
MongoDB is used to persist data, meaning that even when the application is restarted or the user logs out, the data remains stored in the database.
Redux, on the other hand, is used as a state management library to manage the application's state. It is used to store:
User authentication state (login status, user data, etc.)
Application settings (theme, language, etc.)
Temporary data (search results, etc.)
Redux is used to manage the application's state in real-time, allowing for efficient updates and synchronization of data across the application.
In summary:
MongoDB is used for persistent data storage and retrieval.
Redux is used for managing the application's state in real-time.
Here's an analogy to help illustrate the difference:
MongoDB is like a file cabinet where you store important documents (data) that you need to keep for a long time.
Redux is like a sticky note where you jot down temporary reminders (state) that you need to remember for a short time.
While there is some overlap between the two, they serve distinct purposes in the application.
from all these code give summary of what tech stack used and for what purpose
Here is a summary of the tech stack used and their purposes:
Frontend:
React: Used for building the user interface and user experience of the application.
Redux: Used for managing the application's state and ensuring efficient updates and synchronization of data.
Ant Design: Used for providing a consistent and visually appealing user interface.
Backend:
Node.js: Used for creating the server-side API and handling requests from the frontend.
Express.js: Used as a framework for building the Node.js API.
MongoDB: Used as the database management system for storing and retrieving data.
Authentication:
JWT (JSON Web Tokens): Used for authenticating users and ensuring secure access to the application.
Other:
Axios: Used for making HTTP requests from the frontend to the backend API.
Webpack: Used for bundling and optimizing the frontend code.
Babel: Used for transpiling modern JavaScript code to ensure compatibility with older browsers.
Overall, this tech stack is well-suited for building a scalable and maintainable full-stack application with a robust user interface and efficient data management.
explain the project overall in detailASSISTANT
Certainly! Here's a comprehensive overview of the **Doctor Appointment System** built using the **MERN stack** (MongoDB, Express.js, React.js, Node.js), incorporating the detailed code snippets and functionalities you've provided. This explanation is structured to help you convey the project's architecture, technologies used, and workflow effectively during an interview.
---
## **1. Project Overview**
The **Doctor Appointment System** is a full-stack web application designed to facilitate seamless interactions between patients and doctors. It allows users to:
- **Register and authenticate** themselves.
- **Search and apply** to become doctors.
- **Administer and approve** doctor applications.
- **Book, view, and manage** appointments with approved doctors.
- **Receive and manage** notifications regarding appointments and status updates.
The application is built using the **MERN stack**, leveraging MongoDB for database management, Express.js and Node.js for backend APIs, and React.js with Redux for the frontend interface.
---
## **2. Technology Stack and Their Roles**
### **Frontend: React.js**
- **Component-Based Architecture:** Utilizes reusable components for UI elements like forms, tables, and layouts.
- **State Management:** Implements **Redux Toolkit** to manage global state efficiently, handling user data, loading states, and alerts.
- **UI Library:** Employs **Ant Design** for a consistent and professional user interface, providing pre-built components like Tabs, Tables, and Forms.
- **Routing:** Uses **React Router** for managing navigation between different pages and protecting routes based on authentication.
### **Backend: Node.js & Express.js**
- **Server-Side Logic:** Handles API requests, user authentication, data processing, and business logic.
- **Middleware:** Implements custom middleware for tasks like JWT authentication to secure endpoints.
- **RESTful APIs:** Follows REST principles to create scalable and maintainable endpoints for frontend-backend communication.
### **Database: MongoDB**
- **Data Storage:** Stores user profiles, doctor information, appointments, and notifications.
- **Mongoose ODM:** Utilizes Mongoose for schema definitions, data validation, and interaction with MongoDB, ensuring smooth data operations.
### **Authentication: JWT (JSON Web Tokens)**
- **Secure Authentication:** Manages user sessions and secures API endpoints by verifying tokens.
- **Authorization Middleware:** Protects routes by ensuring that only authenticated users can access certain functionalities.
### **State Management: Redux Toolkit**
- **Global State:** Manages application-wide states such as user information and loading indicators.
- **Slices and Reducers:** Defines slices for different state domains (e.g., alerts, user) with associated actions and reducers.
### **HTTP Requests: Axios**
- **API Communication:** Facilitates HTTP requests to backend APIs, handling data fetching, posting, and error management.
### **Utilities and Libraries**
- **bcrypt.js:** Secures user passwords through hashing.
- **moment.js:** Handles date and time formatting and manipulation.
- **colors:** Enhances console logs with colored outputs for better readability during development.
---
## **3. Application Structure and Workflow**
### **3.1. Backend Structure**
- **Models:** Defines data schemas for **Users**, **Doctors**, and **Appointments** using Mongoose.
- **Controllers:** Contains functions to handle various operations like registration, login, doctor application, appointment booking, and notifications.
- **Routes:** Maps HTTP endpoints to corresponding controller functions.
- **Middleware:** Implements JWT authentication to protect sensitive routes.
- **Database Connection:** Establishes a connection to MongoDB, handling successful connections and potential errors.
**Key Backend Files and Their Roles:**
- **`connectDB.js`:** Connects to the MongoDB database using Mongoose.
- **`userController.js`:** Manages user-related operations such as registration, login, authentication, applying to become a doctor, handling notifications, and booking appointments.
- **`doctorController.js`:** Handles doctor-specific functionalities like fetching doctor information, updating profiles, managing appointments, and updating appointment statuses.
- **`adminController.js`:** Oversees administrative tasks including fetching all users and doctors, and changing doctor account statuses.
- **`authMiddleware.js`:** Verifies JWT tokens to authenticate users before granting access to protected routes.
### **3.2. Frontend Structure**
- **Components:** Reusable UI elements like **Spinner**, **PublicRoute**, **ProtectedRoute**, **Layout**, **NotificationPage**, **Doctors**, **Users**, **DoctorAppointments**, **Profile**, **ApplyDoctor**, **Appointments**, and **BookingPage**.
- **Redux Slices:** Manages specific parts of the global state, such as **alerts** and **user** slices.
- **Pages:** Represents different screens of the application, including user registration/login, doctor application, admin panels, appointment booking, and profile management.
- **Routing:** Protects certain routes to ensure only authenticated users or admins can access them.
**Key Frontend Files and Their Roles:**
- **`store.js`:** Configures the Redux store, combining different slices.
- **`alertSlice.js`:** Manages loading states to display or hide loading indicators.
- **`userSlice.js`:** Stores and manages user information globally.
- **`ProtectedRoute.js` & `PublicRoute.js`:** Control access to routes based on authentication status.
- **`Layout.js`:** Provides a consistent layout across different pages.
- **`NotificationPage.js`:** Displays user notifications and allows marking them as read or deleting them.
- **`Doctors.js` & `Users.js`:** Admin panels to manage doctors and users, including approving doctor applications and blocking users.
- **`DoctorAppointments.js`:** Allows doctors to view and update the status of their appointments.
- **`Profile.js` & `ApplyDoctor.js`:** Enable doctors to manage their profiles and apply for doctor status.
- **`Appointments.js` & `BookingPage.js`:** Allow users to view their appointments and book new ones by checking availability.
### **3.3. Application Workflow**
1. **User Registration & Authentication:**
- Users can **register** by providing necessary details, which are validated and stored securely with hashed passwords.
- Upon **login**, users receive a **JWT** token, which is stored in local storage and used for authenticating subsequent requests.
- **Protected routes** ensure that only authenticated users can access certain parts of the application.
2. **Doctor Application & Approval:**
- Authenticated users can **apply to become doctors** by submitting their professional details.
- Admins receive **notifications** about new doctor applications and can **approve or reject** them via the admin panel.
- Approved doctors can **manage their profiles** and **view appointments**.
3. **Appointment Booking:**
- Users can **browse approved doctors** and **book appointments** by selecting available dates and times.
- The system **checks availability** to prevent double bookings.
- Upon successful booking, both the user and the doctor receive **notifications**.
4. **Notifications Management:**
- Users and doctors receive **real-time notifications** for actions like appointment bookings, status updates, and application approvals.
- Notifications can be **marked as read** or **deleted** to keep the notification list organized.
5. **Admin Management:**
- Admins can **view all users** and **doctors**, manage submissions, and **change account statuses**.
- The admin panel provides a centralized interface for overseeing the entire system.
6. **Profile Management:**
- Doctors can **update their profiles**, including personal and professional information, which helps maintain accurate and up-to-date data.
- Users can view their **profile information** and manage their account settings.
---
## **4. Detailed Code Insights**
### **4.1. Backend Controllers**
**User Controller (`userController.js`):**
- **Registration (`registerController`):** Validates user data, hashes passwords using bcrypt, and saves new users to MongoDB.
- **Login (`loginController`):** Authenticates users by comparing provided passwords with hashed passwords and generates JWT tokens upon successful login.
- **Authentication (`authController`):** Retrieves user data based on JWT token, excluding sensitive information like passwords.
- **Doctor Application (`applyDoctorController`):** Allows users to apply for a doctor account, sets the status to pending, and notifies admins.
- **Notifications Management:** Retrieves and deletes notifications, marking them as read.
- **Appointment Booking (`bookAppointmentController`):** Books appointments by saving appointment details and notifying doctors.
- **Availability Check (`bookingAvailabilityController`):** Ensures there are no conflicting appointments before booking.
**Doctor Controller (`doctorController.js`):**
- **Profile Management (`getDoctorInfoController`, `updateProfileController`):** Fetches and updates doctor profiles.
- **Appointment Management (`doctorAppointmentsController`, `updateStatusController`):** Retrieves doctor-specific appointments and updates their statuses (approved/rejected).
**Admin Controller (`adminController.js`):**
- **User & Doctor Management (`getAllUsersController`, `getAllDoctorsController`):** Fetches lists of all users and doctors.
- **Account Status Change (`changeAccountStatusController`):** Approves or rejects doctor applications and updates user roles accordingly.
### **4.2. Frontend Components**
**Authentication Middleware (`authMiddleware.js`):**
- Verifies JWT tokens from the Authorization header.
- Attaches the user ID to the request body upon successful verification.
- Protects routes by ensuring only authenticated requests proceed.
**Redux Setup (`store.js`, `alertSlice.js`, `userSlice.js`):**
- **Store Configuration:** Combines alert and user slices.
- **Alert Slice:** Manages loading states for asynchronous operations.
- **User Slice:** Stores user data globally, accessible across components.
**Routing Components (`ProtectedRoute.js`, `PublicRoute.js`):**
- **ProtectedRoute:** Ensures that only authenticated users can access certain routes, fetching user data if necessary.
- **PublicRoute:** Redirects authenticated users away from routes like login/register to prevent redundant access.
**UI Components:**
- **Spinner:** Displays a loading indicator during asynchronous operations.
- **NotificationPage:** Shows unread and read notifications, allowing users to mark all as read or delete all.
- **Doctors & Users (Admin Panels):** Utilize Ant Design's Table component to list doctors and users with actions to approve, reject, or block accounts.
- **DoctorAppointments:** Enables doctors to view and update the status of their appointments.
- **Profile & ApplyDoctor:** Forms for doctors to manage their profiles or apply for doctor status, handling form submissions and data validation.
- **Appointments & BookingPage:** Allow users to view their appointments and book new ones by selecting available times, checking availability, and finalizing bookings.
### **4.3. Key Code Snippets**
**Database Connection (`connectDB.js`):**
```javascript
const mongoose = require("mongoose");
const colors = require("colors");
const connectDB = async () => {
try {
await mongoose.connect(process.env.MONGO_URL);
console.log(`Mongodb connected ${mongoose.connection.host}`.bgGreen.white);
} catch (error) {
console.log(`Mongodb Server Issue ${error}`.bgRed.white);
}
};
module.exports = connectDB;
```
- Establishes a connection to MongoDB, logging success or errors with colored console messages.
**User Registration Controller:**
```javascript
const registerController = async (req, res) => {
try {
const exisitingUser = await userModel.findOne({ email: req.body.email });
if (exisitingUser) {
return res.status(200).send({ message: "User Already Exist", success: false });
}
const password = req.body.password;
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
req.body.password = hashedPassword;
const newUser = new userModel(req.body);
await newUser.save();
res.status(201).send({ message: "Register Successfully", success: true });
} catch (error) {
console.log(error);
res.status(500).send({
success: false,
message: `Register Controller ${error.message}`,
});
}
};
```
- Handles user registration by checking for existing users, hashing passwords, and saving new user data securely.
**Protected Route Middleware:**
```javascript
const JWT = require("jsonwebtoken");
module.exports = async (req, res, next) => {
try {
const token = req.headers["authorization"].split(" ")[1];
JWT.verify(token, process.env.JWT_SECRET, (err, decode) => {
if (err) {
return res.status(200).send({
message: "Auth Failed",
success: false,
});
} else {
req.body.userId = decode.id;
next();
}
});
} catch (error) {
console.log(error);
res.status(401).send({
message: "Auth Failed",
success: false,
});
}
};
```
- Validates JWT tokens to secure backend routes, attaching user information to requests upon successful verification.
**Redux Slice (`userSlice.js`):**
```javascript
import { createSlice } from "@reduxjs/toolkit";
export const userSlice = createSlice({
name: "user",
initialState: {
user: null,
},
reducers: {
setUser: (state, action) => {
state.user = action.payload;
},
},
});
export const { setUser } = userSlice.actions;
```
- Defines a Redux slice for managing user state across the application.
**Booking Page Component:**
```javascript
const BookingPage = () => {
// State and hooks setup
const { user } = useSelector((state) => state.user);
const params = useParams();
const [doctors, setDoctors] = useState([]);
const [date, setDate] = useState("");
const [time, setTime] = useState();
const [isAvailable, setIsAvailable] = useState(false);
const dispatch = useDispatch();
// Fetch doctor information
const getUserData = async () => {
try {
const res = await axios.post(
"/api/v1/doctor/getDoctorById",
{ doctorId: params.doctorId },
{
headers: {
Authorization: "Bearer " + localStorage.getItem("token"),
},
}
);
if (res.data.success) {
setDoctors(res.data.data);
}
} catch (error) {
console.log(error);
}
};
// Handle availability check
const handleAvailability = async () => {
try {
dispatch(showLoading());
const res = await axios.post(
"/api/v1/user/booking-availability",
{ doctorId: params.doctorId, date, time },
{
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
}
);
dispatch(hideLoading());
if (res.data.success) {
setIsAvailable(true);
message.success(res.data.message);
} else {
message.error(res.data.message);
}
} catch (error) {
dispatch(hideLoading());
console.log(error);
}
};
// Handle appointment booking
const handleBooking = async () => {
try {
setIsAvailable(true);
if (!date && !time) {
return alert("Date & Time Required");
}
dispatch(showLoading());
const res = await axios.post(
"/api/v1/user/book-appointment",
{
doctorId: params.doctorId,
userId: user._id,
doctorInfo: doctors,
userInfo: user,
date: date,
time: time,
},
{
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
}
);
dispatch(hideLoading());
if (res.data.success) {
message.success(res.data.message);
}
} catch (error) {
dispatch(hideLoading());
console.log(error);
}
};
useEffect(() => {
getUserData();
}, []);
return (
<Layout>
<h3>Booking Page</h3>
<div className="container m-2">
{doctors && (
<div>
<h4>
Dr.{doctors.firstName} {doctors.lastName}
</h4>
<h4>Fees : {doctors.feesPerConsultation}</h4>
<h4>
Timings : {doctors.timings && doctors.timings[0]} -{" "}
{doctors.timings && doctors.timings[1]}
</h4>
<div className="d-flex flex-column w-50">
<DatePicker
className="m-2"
format="DD-MM-YYYY"
onChange={(value) => {
setDate(moment(value).format("DD-MM-YYYY"));
}}
/>
<TimePicker
format="HH:mm"
className="mt-3"
onChange={(value) => {
setTime(moment(value).format("HH:mm"));
}}
/>
<button
className="btn btn-primary mt-2"
onClick={handleAvailability}
>
Check Availability
</button>
<button
className="btn btn-dark mt-2"
onClick={handleBooking}
>
Book Now
</button>
</div>
</div>
)}
</div>
</Layout>
);
};
```
- **Functionality:** Allows users to view a doctor's profile, check availability for a selected date and time, and book appointments.
- **State Management:** Utilizes React hooks and Redux for managing user state and loading indicators.
- **API Interaction:** Communicates with backend APIs to fetch doctor data, check availability, and book appointments.
### **4.4. Application Flow Diagram**
```
Patient/User
|
|-- Register/Login
| |
| |-- Backend: Register/Login controllers handle authentication
| |-- Frontend: Forms collect user data, Redux stores user state
|
|-- Apply to Become Doctor
| |
| |-- Backend: ApplyDoctorController stores application, notifies admin
| |-- Frontend: Form submits application details
|
Admin
|
|-- View Doctor Applications
| |
| |-- Backend: Fetches pending doctor applications
| |-- Frontend: Admin panel displays applications, approve/reject actions
|
Approved Doctor
|
|-- Manage Profile
| |
| |-- Backend: Get/Update doctor profile
| |-- Frontend: Profile management form
|
|-- Manage Appointments
| |
| |-- Backend: Fetch appointments, update status
| |-- Frontend: Doctor appointment dashboard
|
Patient/User
|
|-- Browse Doctors
| |
| |-- Backend: Fetch approved doctors
| |-- Frontend: Display doctor listings
|
|-- Book Appointment
| |
| |-- Backend: Check availability, book appointment
| |-- Frontend: Booking form with date/time selection
|
Notifications
|
|-- Receive Updates
|
|-- Backend: Push notifications on status changes
|-- Frontend: Notification center for users and doctors
```
---
## **5. Key Features and Functionalities**
### **5.1. User Authentication**
- **Registration & Login:** Users can create accounts and log in securely. Passwords are hashed using **bcrypt.js** before storage.
- **JWT Tokens:** Upon successful login, users receive a JWT token stored in local storage. This token is used to authenticate and authorize API requests.
- **Protected Routes:** Certain routes are accessible only to authenticated users, ensuring data security and privacy.
### **5.2. Doctor Application and Approval**
- **Application Process:** Registered users can apply to become doctors by submitting professional details. Applications are stored with a "pending" status.
- **Admin Approval:** Admins can view all pending applications, approve or reject them. Approved doctors gain access to additional functionalities like profile management and appointment handling.
- **Notifications:** Admins receive notifications of new applications. Users receive notifications upon approval or rejection of their applications.
### **5.3. Appointment Booking**
- **Browse Doctors:** Users can view a list of approved doctors, including their profiles and availability.
- **Check Availability:** Before booking, the system checks for existing appointments to prevent double booking using the **bookingAvailabilityController**.
- **Book Appointments:** Users can select available dates and times to book appointments. Upon booking, both user and doctor receive notifications.
- **Manage Appointments:** Users can view their booked appointments, cancel or reschedule them as needed.
### **5.4. Notifications System**
- **Real-Time Updates:** Users and doctors receive notifications for important events like new appointments, status changes, and application updates.
- **Management:** Users can mark notifications as read or delete them entirely, maintaining an organized notification list.
- **Admin Notifications:** Admins are notified of new doctor applications, enabling timely approvals.
### **5.5. Admin Panel**
- **User Management:** Admins can view all users, including their roles (regular user or doctor), and perform actions like blocking users.
- **Doctor Management:** Admins can view all doctors, approve or reject applications, and oversee doctor activities.
- **System Oversight:** Provides a centralized dashboard for managing the overall system, ensuring smooth operations and user satisfaction.
---
## **6. Security Considerations**
- **Password Security:** Implements **bcrypt.js** for hashing passwords, ensuring that plain-text passwords are never stored.
- **JWT Authentication:** Uses secure tokens for authenticating users, protecting sensitive API endpoints from unauthorized access.
- **Input Validation:** Ensures that all user inputs are validated both on the frontend and backend to prevent malicious data entry.
- **Error Handling:** Properly manages errors and exceptions to prevent application crashes and provide meaningful feedback to users.
---
## **7. Deployment and Environment Management**
- **Environment Variables:** Utilizes environment variables for sensitive data like database URLs and JWT secrets, enhancing security.
- **Deployment:** The application can be deployed on platforms like **Heroku** or **Vercel** for the frontend, and **Heroku** or similar services for the backend, with MongoDB hosted on services like **MongoDB Atlas**.
- **CI/CD:** Implements continuous integration and deployment practices to ensure smooth updates and maintenance.
---
## **8. Conclusion**
The **Doctor Appointment System** is a robust application built using the MERN stack, demonstrating a comprehensive understanding of full-stack development principles. It incorporates essential features like user authentication, role-based access control, dynamic appointment booking, and real-time notifications, all while ensuring scalability, security, and maintainability.
By leveraging technologies like React for the frontend, Express.js and Node.js for the backend, and MongoDB for the database, the application provides a seamless and efficient platform for managing doctor appointments. Redux facilitates effective state management, ensuring that the user experience remains consistent and responsive.
This project not only showcases technical proficiency but also emphasizes the importance of user-centric design, security best practices, and efficient data management in building successful web applications.
---
**Preparing for the Interview:**
When presenting this project in an interview:
1. **Start with the Overview:** Briefly describe the purpose and main functionalities of the application.
2. **Explain the Tech Stack:** Highlight why each technology was chosen and its role in the project.
3. **Dive into Key Features:** Discuss how user authentication, doctor management, appointment booking, and notifications work.
4. **Showcase Code Snippets:** Reference specific parts of the code that demonstrate critical functionalities, like JWT authentication or booking logic.
5. **Emphasize Security:** Talk about measures taken to secure user data and protect the application.
6. **Discuss Challenges and Solutions:** Share any challenges faced during development and how they were addressed.
7. **Conclude with Learnings:** Reflect on what was learned through this project and how it can be applied to future work.
By following this structure, you'll provide a clear, detailed, and engaging explanation of your Doctor Appointment System, effectively showcasing your skills and understanding of the MERN stack.