create-steve-rogers 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/HMSR/backend/.env.example +6 -0
- package/apps/HMSR/backend/config/db.js +14 -0
- package/apps/HMSR/backend/database/schema.sql +55 -0
- package/apps/HMSR/backend/database/seed.js +53 -0
- package/apps/HMSR/backend/middleware/auth.js +26 -0
- package/apps/HMSR/backend/package-lock.json +1130 -0
- package/apps/HMSR/backend/package.json +19 -0
- package/apps/HMSR/backend/routes/appointments.js +157 -0
- package/apps/HMSR/backend/routes/auth.js +115 -0
- package/apps/HMSR/backend/routes/medicalReports.js +126 -0
- package/apps/HMSR/backend/routes/patients.js +103 -0
- package/apps/HMSR/backend/routes/reports.js +60 -0
- package/apps/HMSR/backend/server.js +38 -0
- package/apps/HMSR/frontend/package-lock.json +17217 -0
- package/apps/HMSR/frontend/package.json +23 -0
- package/apps/HMSR/frontend/public/index.html +17 -0
- package/apps/HMSR/frontend/src/App.js +91 -0
- package/apps/HMSR/frontend/src/components/Layout.js +58 -0
- package/apps/HMSR/frontend/src/components/PrivateRoute.js +25 -0
- package/apps/HMSR/frontend/src/context/AuthContext.js +54 -0
- package/apps/HMSR/frontend/src/index.css +581 -0
- package/apps/HMSR/frontend/src/index.js +17 -0
- package/apps/HMSR/frontend/src/pages/Appointments.js +250 -0
- package/apps/HMSR/frontend/src/pages/Dashboard.js +116 -0
- package/apps/HMSR/frontend/src/pages/Login.js +73 -0
- package/apps/HMSR/frontend/src/pages/MedicalReports.js +217 -0
- package/apps/HMSR/frontend/src/pages/Patients.js +196 -0
- package/apps/HMSR/frontend/src/pages/Register.js +98 -0
- package/apps/HMSR/frontend/src/pages/Reports.js +170 -0
- package/apps/HMSR/frontend/src/services/api.js +15 -0
- package/apps/config.js +8 -0
- package/exclude.txt +1 -0
- package/index.js +55 -0
- package/package.json +14 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const mysql = require('mysql2/promise');
|
|
2
|
+
require('dotenv').config();
|
|
3
|
+
|
|
4
|
+
const pool = mysql.createPool({
|
|
5
|
+
host: process.env.DB_HOST || 'localhost',
|
|
6
|
+
user: process.env.DB_USER || 'root',
|
|
7
|
+
password: process.env.DB_PASSWORD || '',
|
|
8
|
+
database: process.env.DB_NAME || 'hms_kfh_rwanda',
|
|
9
|
+
waitForConnections: true,
|
|
10
|
+
connectionLimit: 10,
|
|
11
|
+
queueLimit: 0,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
module.exports = pool;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
-- King Faisal Hospital Rwanda - HMS Database Schema
|
|
2
|
+
CREATE DATABASE IF NOT EXISTS hms_kfh_rwanda;
|
|
3
|
+
USE hms_kfh_rwanda;
|
|
4
|
+
|
|
5
|
+
DROP TABLE IF EXISTS medical_reports;
|
|
6
|
+
DROP TABLE IF EXISTS appointments;
|
|
7
|
+
DROP TABLE IF EXISTS patients;
|
|
8
|
+
DROP TABLE IF EXISTS users;
|
|
9
|
+
|
|
10
|
+
CREATE TABLE users (
|
|
11
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
12
|
+
full_name VARCHAR(150) NOT NULL,
|
|
13
|
+
email VARCHAR(150) NOT NULL UNIQUE,
|
|
14
|
+
password VARCHAR(255) NOT NULL,
|
|
15
|
+
role ENUM('receptionist', 'doctor') NOT NULL,
|
|
16
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
CREATE TABLE patients (
|
|
20
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
21
|
+
full_name VARCHAR(150) NOT NULL,
|
|
22
|
+
gender ENUM('Male', 'Female', 'Other') NOT NULL,
|
|
23
|
+
date_of_birth DATE NOT NULL,
|
|
24
|
+
phone_number VARCHAR(30) NOT NULL,
|
|
25
|
+
address TEXT NOT NULL,
|
|
26
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE TABLE appointments (
|
|
30
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
31
|
+
patient_id INT NOT NULL,
|
|
32
|
+
doctor_id INT NOT NULL,
|
|
33
|
+
appointment_date DATE NOT NULL,
|
|
34
|
+
appointment_time TIME NOT NULL,
|
|
35
|
+
status ENUM('scheduled', 'completed', 'cancelled') DEFAULT 'scheduled',
|
|
36
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
37
|
+
FOREIGN KEY (patient_id) REFERENCES patients(id) ON DELETE CASCADE,
|
|
38
|
+
FOREIGN KEY (doctor_id) REFERENCES users(id) ON DELETE RESTRICT
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
CREATE TABLE medical_reports (
|
|
42
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
43
|
+
appointment_id INT NOT NULL UNIQUE,
|
|
44
|
+
patient_id INT NOT NULL,
|
|
45
|
+
doctor_id INT NOT NULL,
|
|
46
|
+
diagnosis TEXT NOT NULL,
|
|
47
|
+
prescription TEXT NOT NULL,
|
|
48
|
+
report_date DATE NOT NULL,
|
|
49
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
50
|
+
FOREIGN KEY (appointment_id) REFERENCES appointments(id) ON DELETE CASCADE,
|
|
51
|
+
FOREIGN KEY (patient_id) REFERENCES patients(id) ON DELETE CASCADE,
|
|
52
|
+
FOREIGN KEY (doctor_id) REFERENCES users(id) ON DELETE RESTRICT
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
-- Run: npm run seed (after creating .env) to add demo users
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const bcrypt = require('bcryptjs');
|
|
2
|
+
const mysql = require('mysql2/promise');
|
|
3
|
+
require('dotenv').config({ path: require('path').join(__dirname, '..', '.env') });
|
|
4
|
+
|
|
5
|
+
async function seed() {
|
|
6
|
+
const connection = await mysql.createConnection({
|
|
7
|
+
host: process.env.DB_HOST || 'localhost',
|
|
8
|
+
user: process.env.DB_USER || 'root',
|
|
9
|
+
password: process.env.DB_PASSWORD || '',
|
|
10
|
+
database: process.env.DB_NAME || 'hms_kfh_rwanda',
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const users = [
|
|
14
|
+
{
|
|
15
|
+
full_name: 'Marie Uwase',
|
|
16
|
+
email: 'reception@kfh.rw',
|
|
17
|
+
password: 'receptionist123',
|
|
18
|
+
role: 'receptionist',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
full_name: 'Dr. Jean Pierre Nkurunziza',
|
|
22
|
+
email: 'doctor1@kfh.rw',
|
|
23
|
+
password: 'doctor123',
|
|
24
|
+
role: 'doctor',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
full_name: 'Dr. Alice Mukamana',
|
|
28
|
+
email: 'doctor2@kfh.rw',
|
|
29
|
+
password: 'doctor123',
|
|
30
|
+
role: 'doctor',
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
console.log('Seeding users...');
|
|
35
|
+
for (const user of users) {
|
|
36
|
+
const hashed = await bcrypt.hash(user.password, 10);
|
|
37
|
+
await connection.query(
|
|
38
|
+
`INSERT INTO users (full_name, email, password, role)
|
|
39
|
+
VALUES (?, ?, ?, ?)
|
|
40
|
+
ON DUPLICATE KEY UPDATE full_name = VALUES(full_name), password = VALUES(password)`,
|
|
41
|
+
[user.full_name, user.email, hashed, user.role]
|
|
42
|
+
);
|
|
43
|
+
console.log(` ${user.email} / ${user.password}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
await connection.end();
|
|
47
|
+
console.log('Seed complete.');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
seed().catch((err) => {
|
|
51
|
+
console.error(err);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const jwt = require('jsonwebtoken');
|
|
2
|
+
|
|
3
|
+
const authenticate = (req, res, next) => {
|
|
4
|
+
const header = req.headers.authorization;
|
|
5
|
+
if (!header || !header.startsWith('Bearer ')) {
|
|
6
|
+
return res.status(401).json({ message: 'Access denied. No token provided.' });
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
const token = header.split(' ')[1];
|
|
11
|
+
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
|
12
|
+
req.user = decoded;
|
|
13
|
+
next();
|
|
14
|
+
} catch {
|
|
15
|
+
return res.status(401).json({ message: 'Invalid or expired token.' });
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const authorize = (...roles) => (req, res, next) => {
|
|
20
|
+
if (!roles.includes(req.user.role)) {
|
|
21
|
+
return res.status(403).json({ message: 'You do not have permission for this action.' });
|
|
22
|
+
}
|
|
23
|
+
next();
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
module.exports = { authenticate, authorize };
|