Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Backend/.env
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
PORT = 5000
MONGODB_URL = mongodb+srv://Healthsync_data:pL4vYIRxN7L3SEir@cluster0.57ywj.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0
JWT_SECRET_kEY = "kxrWhWOqleunI+fSNaTGzD2eENVeJO0o2qTyUCYfUf/0IRhO9Taeqs+o7CXFqt6qcwCFuKlwxzWOa2kzZJm117qn6HcZCV5veZWfCMCR6uE04dvSsnbmUvtmr6NurYL7Wmk5uAtOTJW0/QZA5VUf0kEXtV5PU0af/V6a2BLgB5GX005488JHGWBJbIRqXDSaxR/Ne+a4jmsM2FQVpEqRP00cNWmlhvfmGiek0Za7DfuDmRMgmS0PsMr9sry8f+nvAp4OTz6AGJ4="
JWT_SECRET_KEY = kxrWhWOqleunI+fSNaTGzD2eENVeJO0o2qTyUCYfUf/0IRhO9Taeqs+o7CXFqt6qcwCFuKlwxzWOa2kzZJm117qn6HcZCV5veZWfCMCR6uE04dvSsnbmUvtmr6NurYL7Wmk5uAtOTJW0/QZA5VUf0kEXtV5PU0af/V6a2BLgB5GX005488JHGWBJbIRqXDSaxR/Ne+a4jmsM2FQVpEqRP00cNWmlhvfmGiek0Za7DfuDmRMgmS0PsMr9sry8f+nvAp4OTz6AGJ4=
STRIPE_SECRET_KEY=sk_test_51Qvu25KsK9fpnXzm8ehU2ujA7p4UTTJeNIV44GzoO5PtXhNOcoyGRXm8Hz9Vos3mqne0Dq5NXcQIIu9iwNuOe1Ln00b8oKsjTL
CLIENT_SITE_URL =http://localhost:5173
EMAIL_USER=krutagya.kaneria.cg@gmail.com
Expand Down
15 changes: 10 additions & 5 deletions Backend/Controllers/authController.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import dotenv from "dotenv";
dotenv.config();

const generateToken = (user) => {

return jwt.sign(
{ id: user._id, role: user.role },
process.env.JWT_SECRET_KEY,
Expand Down Expand Up @@ -80,16 +81,19 @@ export const register = async (req, res) => {

export const login = async (req, res) => {
const { email } = req.body;



try {
let user = null;

const patient = await User.findOne({ email });
const doctor = await Doctor.findOne({ email });



if (patient) user = patient;
if (doctor) user = doctor;



if (!user) {
return res.status(404).json({ message: "User not found" });
}
Expand All @@ -98,10 +102,11 @@ export const login = async (req, res) => {
if (!isPasswordMatch) {
return res.status(400).json({ status: false, message: "Invalid credentials" });
}

const token = generateToken(user);

const { password, role, appointments, ...rest } = user._doc;

res.status(200).json({
status: true,
message: "Successfully logged in",
Expand Down
6 changes: 6 additions & 0 deletions Backend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ io.on('connection', (socket) => {
console.log(`User ${userId} joined room`);
});

socket.on('emergency_alert', (data)=>{
console.log("Received emergency alert", data);
io.emit("new_emergency_alert", data);
//SMS and email aletr go here...
})

socket.on('disconnect', () => {
console.log('A client disconnected:', socket.id);
});
Expand Down
74 changes: 67 additions & 7 deletions Frountend/src/Dashboard/doctor-account/DashBoard.jsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,53 @@
import React, { useState } from 'react'
import React, { useState, useEffect } from 'react'
import Loader from '../../components/Loader/Loading.jsx';
import Error from "../../components/Error/Error.jsx";
import useGetProfile from '../../hooks/useFetchData.jsx'
import { BASE_URL } from '../../config';
import { BASE_URL, SOCKET_URL } from '../../config';
import Tabs from './Tabs';
import starIcon from '../../assets/images/Star.png'
import DoctorAbout from '../../pages/Docters/DoctorAbout.jsx';
import Profile from './Profile.jsx';
import Appointments from './Appointment.jsx';
import { io } from 'socket.io-client';

const socket = io(SOCKET_URL) // setting up socket connection

const DashBoard = () => {


const {data,loading,error} = useGetProfile(`${BASE_URL}/doctors/profile/me`);

const [emergencyMsg, setEmergencyMsg] = useState('')
const [tab,setTab] = useState('overview')


const [address, setAddress] = useState("");

const getAddress = async (lat, lng) => {
const response = await fetch(
`https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${lat}&lon=${lng}`
);
const data = await response.json();
setAddress(data.display_name);
};


//listen for incoming emergency messages
useEffect(() => {
console.log("In use effect");

// Confirm socket connected
socket.on('connect', () => {
console.log('Socket connected with ID:', socket.id);
});

// Listen for emergency alerts
socket.on('new_emergency_alert', (data) => {
setEmergencyMsg(data);
getAddress(data.location.latitude,data.location.longitude)
});

return () => {
socket.off('new_emergency_alert');
socket.off('connect');
};
}, []);

return (
<section>
<div className='max-w-[1170px] px-5 mx-auto'>
Expand All @@ -26,6 +56,34 @@ const DashBoard = () => {

{
!loading && !error && (
<div>
{/* Emergency alert goes below */} {emergencyMsg!=="" &&
<div className='flex p-4 mb-4 text-white bg-red-400 rounded-lg'>
<svg
aria-hidden="true"
className="flex-shrink-0 w-5 h-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
d="M18 10A8 8 0 11 2 10a8 8 0 0116 0zM9 4a1 1 0 012 0v4a1 1 0 01-2 0V4zm0 8a1 1 0 102 0 1 1 0 00-2 0z"
clipRule="evenodd"
/>
</svg>

<span className='sr-only'>Emergency</span>
<div className='ml-3 text-sm font-medium'>
<div>Emergency! {emergencyMsg && emergencyMsg.name ? emergencyMsg.name : "Unknown" } has an emergency.</div>
{address && (
<div className='text-xs text-white mt-1'>
Location: {address}
</div>
)}

</div>
</div> }
<div className='grid lg:grid-cols-3 gap-[30px] lg:gap-[50px]'>
<Tabs tab={tab} setTab={setTab}/>
<div className='lg:col-span-2'>
Expand Down Expand Up @@ -92,9 +150,11 @@ const DashBoard = () => {
)}
{tab==='appointments' && <Appointments appointments={data.appointments} /> }
{tab==='settings' && <Profile doctorData={data} /> }

</div>
</div>
</div>
</div>
)}
</div>
</section>
Expand Down
2 changes: 1 addition & 1 deletion Frountend/src/Dashboard/doctor-account/Tabs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const Tabs = ({tab,setTab}) => {
<div>
<span className='lg:hidden'>
<BiMenu className='w-6 h-6 cursor-pointer'/>
</span>
</span>
<div className='hidden lg:flex flex-col p-[30px] bg-white shadow-panelShadow items-center h-max rounded-md'>
<button onClick={()=>setTab('overview')}
className={`${
Expand Down
57 changes: 51 additions & 6 deletions Frountend/src/components/Header/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ import Logo from "../../assets/images/logo.png"
import {BiMenu} from "react-icons/bi"
import {NavLink,Link} from 'react-router-dom'
import "../../App.css"
import useGetProfile from '../../hooks/useFetchData.jsx';
import { BASE_URL } from '../../config';
import { authContext } from '../../context/AuthContext'
import io from 'socket.io-client';

const socket = io('http://localhost:5000');

const navLinks = [
{
Expand Down Expand Up @@ -54,6 +58,42 @@ const Header = () => {

const toggleMenu = () => menuRef.current.classList.toggle('show_menu')

const handleEmergency = () => {
const confirmed = window.confirm("Are you sure you want to send an emergency alert?");
if (!confirmed) {
console.log("Emergency alert cancelled!");
return;
}
//fetch the location of the user
navigator.geolocation.getCurrentPosition((position)=>{
const location = {
latitude: position.coords.latitude,
longitude: position.coords.longitude
};
sendEmergencyData(location);
},
(error) => {
console.log("Location access denied or unavaiable", error.message);
sendEmergencyData(null);
}
)
}

const { data: userData, loading, error } = useGetProfile(`${BASE_URL}/users/profile/me`);

const sendEmergencyData = (location) => {
//all the data that is necessary bundled into an object
const emergencyData = {
patientId: userData._id,
name: userData.name,
location: location,
time: new Date().toISOString()
}
console.log("Emitting emergency alert");
socket.emit("emergency_alert", emergencyData)
alert("Emergency alert sent")
}

return (
<header className=" header flex items-center" ref={headerRef}>
<div className='container'>
Expand Down Expand Up @@ -83,13 +123,18 @@ const Header = () => {

<div className='flex items-center gap-4'>
{token && user ? (
<div>
<Link to={`${role==='doctor' ? '/doctors/profile/me' : 'users/profile/me'}`}>
<figure className='w-[35px] h-[35px] rounded-full cursor-pointer'>
<img src={user?.photo} className='w-full rounded-full' alt="" />
</figure>
<div className="flex items-center gap-3">
{role==="patient" && (<button className="bg-red-600 text-white px-3 py-2 rounded-md text-sm leading-none hover:bg-red-700 transition" onClick={handleEmergency}>
Emergency
</button>)}

<Link to={`${role === 'doctor' ? '/doctors/profile/me' : 'users/profile/me'}`}>
<figure className="w-[35px] h-[35px] rounded-full overflow-hidden cursor-pointer">
<img src={user?.photo} className="w-full h-full object-cover" alt="Profile" />
</figure>
</Link>
</div> ) : (
</div>
) : (
<Link to='/login'>
<button className='bg-primaryColor py-2 px-6 text-white font-[600] h-[44px] flex items-center justify-center rounded-[50px]'>Login</button>
</Link>
Expand Down
1 change: 1 addition & 0 deletions Frountend/src/config.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export const BASE_URL = "http://localhost:5000/api/v1";
export const SOCKET_URL = "http://localhost:5000"
export const token = localStorage.getItem('token')
3 changes: 2 additions & 1 deletion Frountend/src/pages/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const Login = () => {
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData),
});

console.log(res);

const result = await res.json();
if (!res.ok) {
throw new Error(result.message || "Login Failed");
Expand Down