Skip to content

Commit b2d6e9a

Browse files
committed
Add user authentication and statistics endpoints
- Introduced user login functionality with JWT token generation. - Added user management routes for fetching all users and user login. - Implemented new statistics endpoints for total counts of appointments, doctors, lab tests, and medicines. - Updated existing controllers and routes to integrate new features. - Enhanced the admin dashboard to display user and hospital statistics. - Refactored lab component to support adding, editing, and deleting lab tests.
1 parent 8c7eb90 commit b2d6e9a

20 files changed

+609
-204
lines changed

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/node_modules
2+
/back_end/node_modules
3+
/back_end/.env
4+
/front_end/.env
5+
/front_end/node_modules
6+
/front_end/build
7+
/front_end/node_modules
8+
/front_end/.env
9+
/front_end/build
10+
/front_end/node_modules
11+
/front_end/.env

back_end/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules/
2+
.env
23

back_end/controller/appointmentController.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,32 @@ const submitFeedback = async (req, res) => {
164164
}
165165
};
166166

167+
const getTotalAppointmentsCount = async (req, res) => {
168+
try {
169+
const result = await sql.query`SELECT COUNT(*) AS total FROM Appointments`;
170+
res.status(200).json({ total: result.recordset[0].total });
171+
} catch (err) {
172+
console.error('Error fetching total appointment count:', err);
173+
res.status(500).json({ error: 'Failed to fetch appointment count' });
174+
}
175+
};
176+
177+
const getTotalBillingCount = async (req, res) => {
178+
try {
179+
const result = await sql.query`SELECT COUNT(*) AS total FROM Billing`;
180+
res.status(200).json({ total: result.recordset[0].total });
181+
} catch (err) {
182+
console.error('Error fetching total billing count:', err);
183+
res.status(500).json({ error: 'Failed to fetch billing count' });
184+
}
185+
};
186+
167187
module.exports = {
168188
createAppointment,
169189
getAppointmentsByDoctor,
170190
getAppointmentsByPatient,
171191
updateAppointmentStatus,
172-
submitFeedback
192+
submitFeedback,
193+
getTotalAppointmentsCount,
194+
getTotalBillingCount
173195
};

back_end/controller/doctorController.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,19 @@ const getDoctorAvailability = async (req, res) => {
9999
}
100100
};
101101

102+
const getTotalDoctorsCount = async (req, res) => {
103+
try {
104+
const result = await sql.query`SELECT COUNT(*) AS total FROM Doctors`;
105+
res.status(200).json({ total: result.recordset[0].total });
106+
} catch (err) {
107+
console.error('Error fetching total doctor count:', err);
108+
res.status(500).json({ error: 'Failed to fetch doctor count' });
109+
}
110+
};
111+
102112
module.exports = {
103113
getAllDoctors,
104114
getDoctorById,
105-
getDoctorAvailability
115+
getDoctorAvailability,
116+
getTotalDoctorsCount,
106117
};

back_end/controller/labController.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,23 @@ const getTestsByPatient = async (req, res) => {
177177
}
178178
};
179179

180+
const getTotalLabTestsCount = async (req, res) => {
181+
try {
182+
const result = await sql.query`SELECT COUNT(*) AS total FROM LabTests`;
183+
res.status(200).json({ total: result.recordset[0].total });
184+
} catch (err) {
185+
console.error('Error fetching total lab tests count:', err);
186+
res.status(500).json({ error: 'Failed to fetch lab tests count' });
187+
}
188+
};
189+
180190
module.exports = {
181191
getAllTests,
182192
getTestById,
183193
createTest,
184194
updateTest,
185195
deleteTest,
186196
getTestsByStatus,
187-
getTestsByPatient
197+
getTestsByPatient,
198+
getTotalLabTestsCount
188199
};

back_end/controller/patientController.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const sql = require('mssql');
22

3+
34
// Get total number of patients
45
exports.getTotalPatientsCount = async (req, res) => {
56
try {

back_end/controller/pharmacyController.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,20 @@ const deleteMedicine = async (req, res) => {
8282
}
8383
};
8484

85+
const getTotalMedicinesCount = async (req, res) => {
86+
try {
87+
const result = await sql.query`SELECT COUNT(*) AS total FROM Pharmacy`;
88+
res.status(200).json({ total: result.recordset[0].total });
89+
} catch (err) {
90+
console.error('Error fetching total medicine count:', err);
91+
res.status(500).json({ error: 'Failed to fetch medicine count' });
92+
}
93+
};
94+
8595
module.exports = {
8696
getAllMedicines,
8797
addMedicine,
8898
updateMedicine,
89-
deleteMedicine
99+
deleteMedicine,
100+
getTotalMedicinesCount,
90101
};
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
const sql = require('mssql');
2+
const bcrypt = require('bcryptjs');
3+
const jwt = require('jsonwebtoken');
4+
5+
const loginUser = async (req, res) => {
6+
const { username, password } = req.body;
7+
if (!username || !password) {
8+
return res.status(400).json({ message: 'Username and password are required.' });
9+
}
10+
try {
11+
const request = new sql.Request();
12+
request.input('username', sql.VarChar(50), username);
13+
const result = await request.query(`SELECT * FROM Users WHERE username = @username`);
14+
if (result.recordset.length === 0) {
15+
return res.status(401).json({ message: 'Invalid username or password.' });
16+
}
17+
const user = result.recordset[0];
18+
let passwordMatch = false;
19+
try {
20+
passwordMatch = await bcrypt.compare(password, user.password_hash);
21+
} catch (e) {
22+
passwordMatch = false;
23+
}
24+
// TEMPORARY: Allow plain text password match for testing
25+
if (!passwordMatch && password === user.password_hash) {
26+
passwordMatch = true;
27+
}
28+
if (!passwordMatch) {
29+
return res.status(401).json({ message: 'Invalid username or password.' });
30+
}
31+
// Generate JWT
32+
const token = jwt.sign({ user_id: user.user_id, role: user.role, full_name: user.full_name }, process.env.JWT_SECRET || 'secret', { expiresIn: '1d' });
33+
res.json({ token, user: { user_id: user.user_id, username: user.username, role: user.role, full_name: user.full_name, email: user.email, phone: user.phone } });
34+
} catch (err) {
35+
console.error('Login error:', err);
36+
res.status(500).json({ message: 'Server error', error: err.message });
37+
}
38+
};
39+
40+
const getAllUsers = async (req, res) => {
41+
try {
42+
const request = new sql.Request();
43+
const result = await request.query('SELECT user_id, username, role, full_name, email, phone FROM Users');
44+
res.json(result.recordset);
45+
} catch (err) {
46+
console.error('Error fetching users:', err);
47+
res.status(500).json({ message: 'Error fetching users', error: err.message });
48+
}
49+
};
50+
51+
module.exports = { loginUser, getAllUsers };

back_end/routes/appointmentRoutes.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ const {
55
getAppointmentsByDoctor,
66
getAppointmentsByPatient,
77
updateAppointmentStatus,
8-
submitFeedback
8+
submitFeedback,
9+
getTotalAppointmentsCount,
10+
getTotalBillingCount
911
} = require('../controller/appointmentController');
1012

1113
// Add these routes
@@ -14,5 +16,7 @@ router.post('/feedback', submitFeedback); // POST /api/appointments/feedback
1416
router.get('/doctor/:doctorId', getAppointmentsByDoctor);
1517
router.get('/patient/:patientId', getAppointmentsByPatient);
1618
router.put('/:id/status', updateAppointmentStatus);
19+
router.get('/stats/total', getTotalAppointmentsCount);
20+
router.get('/stats/billing', getTotalBillingCount);
1721

1822
module.exports = router;

back_end/routes/doctorRoutes.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
const express = require('express');
2-
const {
3-
getAllDoctors,
4-
getDoctorById,
5-
getDoctorAvailability
6-
} = require('../controller/doctorController');
7-
2+
const { getAllDoctors, getDoctorById, getDoctorAvailability, getTotalDoctorsCount } = require('../controller/doctorController');
83
const router = express.Router();
94

105
router.get('/', getAllDoctors); // GET all doctors
116
router.get('/:id', getDoctorById); // GET doctor by ID
127
router.get('/:id/availability', getDoctorAvailability); // GET doctor availability
8+
router.get('/stats/total', getTotalDoctorsCount);
139

1410
module.exports = router;

0 commit comments

Comments
 (0)