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.
Files changed (34) hide show
  1. package/apps/HMSR/backend/.env.example +6 -0
  2. package/apps/HMSR/backend/config/db.js +14 -0
  3. package/apps/HMSR/backend/database/schema.sql +55 -0
  4. package/apps/HMSR/backend/database/seed.js +53 -0
  5. package/apps/HMSR/backend/middleware/auth.js +26 -0
  6. package/apps/HMSR/backend/package-lock.json +1130 -0
  7. package/apps/HMSR/backend/package.json +19 -0
  8. package/apps/HMSR/backend/routes/appointments.js +157 -0
  9. package/apps/HMSR/backend/routes/auth.js +115 -0
  10. package/apps/HMSR/backend/routes/medicalReports.js +126 -0
  11. package/apps/HMSR/backend/routes/patients.js +103 -0
  12. package/apps/HMSR/backend/routes/reports.js +60 -0
  13. package/apps/HMSR/backend/server.js +38 -0
  14. package/apps/HMSR/frontend/package-lock.json +17217 -0
  15. package/apps/HMSR/frontend/package.json +23 -0
  16. package/apps/HMSR/frontend/public/index.html +17 -0
  17. package/apps/HMSR/frontend/src/App.js +91 -0
  18. package/apps/HMSR/frontend/src/components/Layout.js +58 -0
  19. package/apps/HMSR/frontend/src/components/PrivateRoute.js +25 -0
  20. package/apps/HMSR/frontend/src/context/AuthContext.js +54 -0
  21. package/apps/HMSR/frontend/src/index.css +581 -0
  22. package/apps/HMSR/frontend/src/index.js +17 -0
  23. package/apps/HMSR/frontend/src/pages/Appointments.js +250 -0
  24. package/apps/HMSR/frontend/src/pages/Dashboard.js +116 -0
  25. package/apps/HMSR/frontend/src/pages/Login.js +73 -0
  26. package/apps/HMSR/frontend/src/pages/MedicalReports.js +217 -0
  27. package/apps/HMSR/frontend/src/pages/Patients.js +196 -0
  28. package/apps/HMSR/frontend/src/pages/Register.js +98 -0
  29. package/apps/HMSR/frontend/src/pages/Reports.js +170 -0
  30. package/apps/HMSR/frontend/src/services/api.js +15 -0
  31. package/apps/config.js +8 -0
  32. package/exclude.txt +1 -0
  33. package/index.js +55 -0
  34. package/package.json +14 -0
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "hms-backend",
3
+ "version": "1.0.0",
4
+ "description": "King Faisal Hospital Rwanda - Appointment & Medical Report API",
5
+ "main": "server.js",
6
+ "scripts": {
7
+ "start": "node server.js",
8
+ "dev": "node --watch server.js",
9
+ "seed": "node database/seed.js"
10
+ },
11
+ "dependencies": {
12
+ "bcryptjs": "^2.4.3",
13
+ "cors": "^2.8.5",
14
+ "dotenv": "^16.4.5",
15
+ "express": "^4.21.0",
16
+ "jsonwebtoken": "^9.0.2",
17
+ "mysql2": "^3.11.0"
18
+ }
19
+ }
@@ -0,0 +1,157 @@
1
+ const express = require('express');
2
+ const pool = require('../config/db');
3
+ const { authenticate, authorize } = require('../middleware/auth');
4
+
5
+ const router = express.Router();
6
+
7
+ const appointmentSelect = `
8
+ SELECT a.*,
9
+ p.full_name AS patient_name,
10
+ u.full_name AS doctor_name
11
+ FROM appointments a
12
+ JOIN patients p ON a.patient_id = p.id
13
+ JOIN users u ON a.doctor_id = u.id
14
+ `;
15
+
16
+ router.use(authenticate);
17
+
18
+ router.get('/', async (req, res) => {
19
+ try {
20
+ let query = appointmentSelect;
21
+ const params = [];
22
+
23
+ if (req.user.role === 'doctor') {
24
+ query += ' WHERE a.doctor_id = ?';
25
+ params.push(req.user.id);
26
+ }
27
+
28
+ query += ' ORDER BY a.appointment_date DESC, a.appointment_time DESC';
29
+
30
+ const [appointments] = await pool.query(query, params);
31
+ res.json(appointments);
32
+ } catch (err) {
33
+ console.error(err);
34
+ res.status(500).json({ message: 'Failed to fetch appointments.' });
35
+ }
36
+ });
37
+
38
+ router.get('/assigned', authorize('doctor'), async (req, res) => {
39
+ try {
40
+ const [appointments] = await pool.query(
41
+ `${appointmentSelect}
42
+ WHERE a.doctor_id = ? AND a.status = 'scheduled'
43
+ ORDER BY a.appointment_date ASC, a.appointment_time ASC`,
44
+ [req.user.id]
45
+ );
46
+ res.json(appointments);
47
+ } catch (err) {
48
+ console.error(err);
49
+ res.status(500).json({ message: 'Failed to fetch assigned appointments.' });
50
+ }
51
+ });
52
+
53
+ router.post('/', authorize('receptionist'), async (req, res) => {
54
+ try {
55
+ const { patient_id, doctor_id, appointment_date, appointment_time, status } =
56
+ req.body;
57
+
58
+ if (!patient_id || !doctor_id || !appointment_date || !appointment_time) {
59
+ return res.status(400).json({ message: 'Required appointment fields missing.' });
60
+ }
61
+
62
+ const [result] = await pool.query(
63
+ `INSERT INTO appointments (patient_id, doctor_id, appointment_date, appointment_time, status)
64
+ VALUES (?, ?, ?, ?, ?)`,
65
+ [
66
+ patient_id,
67
+ doctor_id,
68
+ appointment_date,
69
+ appointment_time,
70
+ status || 'scheduled',
71
+ ]
72
+ );
73
+
74
+ const [appointment] = await pool.query(
75
+ `${appointmentSelect} WHERE a.id = ?`,
76
+ [result.insertId]
77
+ );
78
+ res.status(201).json(appointment[0]);
79
+ } catch (err) {
80
+ console.error(err);
81
+ res.status(500).json({ message: 'Failed to create appointment.' });
82
+ }
83
+ });
84
+
85
+ router.put('/:id', authorize('receptionist'), async (req, res) => {
86
+ try {
87
+ const { patient_id, doctor_id, appointment_date, appointment_time, status } =
88
+ req.body;
89
+
90
+ const [existing] = await pool.query('SELECT id FROM appointments WHERE id = ?', [
91
+ req.params.id,
92
+ ]);
93
+ if (existing.length === 0) {
94
+ return res.status(404).json({ message: 'Appointment not found.' });
95
+ }
96
+
97
+ await pool.query(
98
+ `UPDATE appointments SET patient_id = ?, doctor_id = ?, appointment_date = ?,
99
+ appointment_time = ?, status = ? WHERE id = ?`,
100
+ [
101
+ patient_id,
102
+ doctor_id,
103
+ appointment_date,
104
+ appointment_time,
105
+ status,
106
+ req.params.id,
107
+ ]
108
+ );
109
+
110
+ const [appointment] = await pool.query(
111
+ `${appointmentSelect} WHERE a.id = ?`,
112
+ [req.params.id]
113
+ );
114
+ res.json(appointment[0]);
115
+ } catch (err) {
116
+ console.error(err);
117
+ res.status(500).json({ message: 'Failed to update appointment.' });
118
+ }
119
+ });
120
+
121
+ router.patch('/:id/cancel', authorize('receptionist'), async (req, res) => {
122
+ try {
123
+ const [result] = await pool.query(
124
+ "UPDATE appointments SET status = 'cancelled' WHERE id = ?",
125
+ [req.params.id]
126
+ );
127
+ if (result.affectedRows === 0) {
128
+ return res.status(404).json({ message: 'Appointment not found.' });
129
+ }
130
+
131
+ const [appointment] = await pool.query(
132
+ `${appointmentSelect} WHERE a.id = ?`,
133
+ [req.params.id]
134
+ );
135
+ res.json(appointment[0]);
136
+ } catch (err) {
137
+ console.error(err);
138
+ res.status(500).json({ message: 'Failed to cancel appointment.' });
139
+ }
140
+ });
141
+
142
+ router.delete('/:id', authorize('receptionist'), async (req, res) => {
143
+ try {
144
+ const [result] = await pool.query('DELETE FROM appointments WHERE id = ?', [
145
+ req.params.id,
146
+ ]);
147
+ if (result.affectedRows === 0) {
148
+ return res.status(404).json({ message: 'Appointment not found.' });
149
+ }
150
+ res.json({ message: 'Appointment deleted successfully.' });
151
+ } catch (err) {
152
+ console.error(err);
153
+ res.status(500).json({ message: 'Failed to delete appointment.' });
154
+ }
155
+ });
156
+
157
+ module.exports = router;
@@ -0,0 +1,115 @@
1
+ const express = require('express');
2
+ const bcrypt = require('bcryptjs');
3
+ const jwt = require('jsonwebtoken');
4
+ const pool = require('../config/db');
5
+ const { authenticate } = require('../middleware/auth');
6
+
7
+ const router = express.Router();
8
+
9
+ router.post('/register', async (req, res) => {
10
+ try {
11
+ const { full_name, email, password, role } = req.body;
12
+
13
+ if (!full_name || !email || !password || !role) {
14
+ return res.status(400).json({ message: 'All fields are required.' });
15
+ }
16
+
17
+ if (!['receptionist', 'doctor'].includes(role)) {
18
+ return res.status(400).json({ message: 'Role must be receptionist or doctor.' });
19
+ }
20
+
21
+ const [existing] = await pool.query('SELECT id FROM users WHERE email = ?', [email]);
22
+ if (existing.length > 0) {
23
+ return res.status(400).json({ message: 'Email already registered.' });
24
+ }
25
+
26
+ const hashed = await bcrypt.hash(password, 10);
27
+ const [result] = await pool.query(
28
+ 'INSERT INTO users (full_name, email, password, role) VALUES (?, ?, ?, ?)',
29
+ [full_name, email, hashed, role]
30
+ );
31
+
32
+ res.status(201).json({
33
+ message: 'Registration successful.',
34
+ user: { id: result.insertId, full_name, email, role },
35
+ });
36
+ } catch (err) {
37
+ console.error(err);
38
+ res.status(500).json({ message: 'Server error during registration.' });
39
+ }
40
+ });
41
+
42
+ router.post('/login', async (req, res) => {
43
+ try {
44
+ const { email, password } = req.body;
45
+
46
+ if (!email || !password) {
47
+ return res.status(400).json({ message: 'Email and password are required.' });
48
+ }
49
+
50
+ const [users] = await pool.query(
51
+ 'SELECT id, full_name, email, password, role FROM users WHERE email = ?',
52
+ [email]
53
+ );
54
+
55
+ if (users.length === 0) {
56
+ return res.status(401).json({ message: 'Invalid email or password.' });
57
+ }
58
+
59
+ const user = users[0];
60
+ const valid = await bcrypt.compare(password, user.password);
61
+ if (!valid) {
62
+ return res.status(401).json({ message: 'Invalid email or password.' });
63
+ }
64
+
65
+ const token = jwt.sign(
66
+ { id: user.id, email: user.email, role: user.role, full_name: user.full_name },
67
+ process.env.JWT_SECRET,
68
+ { expiresIn: '24h' }
69
+ );
70
+
71
+ res.json({
72
+ message: 'Login successful.',
73
+ token,
74
+ user: {
75
+ id: user.id,
76
+ full_name: user.full_name,
77
+ email: user.email,
78
+ role: user.role,
79
+ },
80
+ });
81
+ } catch (err) {
82
+ console.error(err);
83
+ res.status(500).json({ message: 'Server error during login.' });
84
+ }
85
+ });
86
+
87
+ router.get('/me', authenticate, async (req, res) => {
88
+ try {
89
+ const [users] = await pool.query(
90
+ 'SELECT id, full_name, email, role FROM users WHERE id = ?',
91
+ [req.user.id]
92
+ );
93
+ if (users.length === 0) {
94
+ return res.status(404).json({ message: 'User not found.' });
95
+ }
96
+ res.json(users[0]);
97
+ } catch (err) {
98
+ console.error(err);
99
+ res.status(500).json({ message: 'Server error.' });
100
+ }
101
+ });
102
+
103
+ router.get('/doctors', authenticate, async (req, res) => {
104
+ try {
105
+ const [doctors] = await pool.query(
106
+ "SELECT id, full_name, email FROM users WHERE role = 'doctor' ORDER BY full_name"
107
+ );
108
+ res.json(doctors);
109
+ } catch (err) {
110
+ console.error(err);
111
+ res.status(500).json({ message: 'Server error.' });
112
+ }
113
+ });
114
+
115
+ module.exports = router;
@@ -0,0 +1,126 @@
1
+ const express = require('express');
2
+ const pool = require('../config/db');
3
+ const { authenticate, authorize } = require('../middleware/auth');
4
+
5
+ const router = express.Router();
6
+
7
+ const reportSelect = `
8
+ SELECT mr.*,
9
+ p.full_name AS patient_name,
10
+ u.full_name AS doctor_name
11
+ FROM medical_reports mr
12
+ JOIN patients p ON mr.patient_id = p.id
13
+ JOIN users u ON mr.doctor_id = u.id
14
+ `;
15
+
16
+ router.use(authenticate);
17
+
18
+ router.get('/', async (req, res) => {
19
+ try {
20
+ let query = reportSelect;
21
+ const params = [];
22
+
23
+ if (req.user.role === 'doctor') {
24
+ query += ' WHERE mr.doctor_id = ?';
25
+ params.push(req.user.id);
26
+ }
27
+
28
+ query += ' ORDER BY mr.report_date DESC';
29
+
30
+ const [reports] = await pool.query(query, params);
31
+ res.json(reports);
32
+ } catch (err) {
33
+ console.error(err);
34
+ res.status(500).json({ message: 'Failed to fetch medical reports.' });
35
+ }
36
+ });
37
+
38
+ router.post('/', authorize('doctor'), async (req, res) => {
39
+ try {
40
+ const { appointment_id, diagnosis, prescription, report_date } = req.body;
41
+
42
+ if (!appointment_id || !diagnosis || !prescription) {
43
+ return res.status(400).json({ message: 'Appointment, diagnosis, and prescription are required.' });
44
+ }
45
+
46
+ const [appointments] = await pool.query(
47
+ 'SELECT * FROM appointments WHERE id = ? AND doctor_id = ?',
48
+ [appointment_id, req.user.id]
49
+ );
50
+
51
+ if (appointments.length === 0) {
52
+ return res.status(404).json({ message: 'Appointment not found or not assigned to you.' });
53
+ }
54
+
55
+ const appointment = appointments[0];
56
+
57
+ if (appointment.status === 'cancelled') {
58
+ return res.status(400).json({ message: 'Cannot create report for cancelled appointment.' });
59
+ }
60
+
61
+ const [existingReport] = await pool.query(
62
+ 'SELECT id FROM medical_reports WHERE appointment_id = ?',
63
+ [appointment_id]
64
+ );
65
+ if (existingReport.length > 0) {
66
+ return res.status(400).json({ message: 'Medical report already exists for this appointment.' });
67
+ }
68
+
69
+ const date = report_date || new Date().toISOString().split('T')[0];
70
+
71
+ const [result] = await pool.query(
72
+ `INSERT INTO medical_reports (appointment_id, patient_id, doctor_id, diagnosis, prescription, report_date)
73
+ VALUES (?, ?, ?, ?, ?, ?)`,
74
+ [
75
+ appointment_id,
76
+ appointment.patient_id,
77
+ req.user.id,
78
+ diagnosis,
79
+ prescription,
80
+ date,
81
+ ]
82
+ );
83
+
84
+ await pool.query(
85
+ "UPDATE appointments SET status = 'completed' WHERE id = ?",
86
+ [appointment_id]
87
+ );
88
+
89
+ const [report] = await pool.query(`${reportSelect} WHERE mr.id = ?`, [
90
+ result.insertId,
91
+ ]);
92
+ res.status(201).json(report[0]);
93
+ } catch (err) {
94
+ console.error(err);
95
+ res.status(500).json({ message: 'Failed to save medical report.' });
96
+ }
97
+ });
98
+
99
+ router.put('/:id', authorize('doctor'), async (req, res) => {
100
+ try {
101
+ const { diagnosis, prescription, report_date } = req.body;
102
+
103
+ const [existing] = await pool.query(
104
+ 'SELECT id FROM medical_reports WHERE id = ? AND doctor_id = ?',
105
+ [req.params.id, req.user.id]
106
+ );
107
+ if (existing.length === 0) {
108
+ return res.status(404).json({ message: 'Medical report not found.' });
109
+ }
110
+
111
+ await pool.query(
112
+ 'UPDATE medical_reports SET diagnosis = ?, prescription = ?, report_date = ? WHERE id = ?',
113
+ [diagnosis, prescription, report_date, req.params.id]
114
+ );
115
+
116
+ const [report] = await pool.query(`${reportSelect} WHERE mr.id = ?`, [
117
+ req.params.id,
118
+ ]);
119
+ res.json(report[0]);
120
+ } catch (err) {
121
+ console.error(err);
122
+ res.status(500).json({ message: 'Failed to update medical report.' });
123
+ }
124
+ });
125
+
126
+ module.exports = router;
@@ -0,0 +1,103 @@
1
+ const express = require('express');
2
+ const pool = require('../config/db');
3
+ const { authenticate, authorize } = require('../middleware/auth');
4
+
5
+ const router = express.Router();
6
+
7
+ router.use(authenticate);
8
+ router.use(authorize('receptionist'));
9
+
10
+ router.get('/', async (req, res) => {
11
+ try {
12
+ const [patients] = await pool.query(
13
+ 'SELECT * FROM patients ORDER BY full_name ASC'
14
+ );
15
+ res.json(patients);
16
+ } catch (err) {
17
+ console.error(err);
18
+ res.status(500).json({ message: 'Failed to fetch patients.' });
19
+ }
20
+ });
21
+
22
+ router.get('/:id', async (req, res) => {
23
+ try {
24
+ const [patients] = await pool.query('SELECT * FROM patients WHERE id = ?', [
25
+ req.params.id,
26
+ ]);
27
+ if (patients.length === 0) {
28
+ return res.status(404).json({ message: 'Patient not found.' });
29
+ }
30
+ res.json(patients[0]);
31
+ } catch (err) {
32
+ console.error(err);
33
+ res.status(500).json({ message: 'Failed to fetch patient.' });
34
+ }
35
+ });
36
+
37
+ router.post('/', async (req, res) => {
38
+ try {
39
+ const { full_name, gender, date_of_birth, phone_number, address } = req.body;
40
+
41
+ if (!full_name || !gender || !date_of_birth || !phone_number || !address) {
42
+ return res.status(400).json({ message: 'All patient fields are required.' });
43
+ }
44
+
45
+ const [result] = await pool.query(
46
+ `INSERT INTO patients (full_name, gender, date_of_birth, phone_number, address)
47
+ VALUES (?, ?, ?, ?, ?)`,
48
+ [full_name, gender, date_of_birth, phone_number, address]
49
+ );
50
+
51
+ const [patient] = await pool.query('SELECT * FROM patients WHERE id = ?', [
52
+ result.insertId,
53
+ ]);
54
+ res.status(201).json(patient[0]);
55
+ } catch (err) {
56
+ console.error(err);
57
+ res.status(500).json({ message: 'Failed to create patient.' });
58
+ }
59
+ });
60
+
61
+ router.put('/:id', async (req, res) => {
62
+ try {
63
+ const { full_name, gender, date_of_birth, phone_number, address } = req.body;
64
+
65
+ const [existing] = await pool.query('SELECT id FROM patients WHERE id = ?', [
66
+ req.params.id,
67
+ ]);
68
+ if (existing.length === 0) {
69
+ return res.status(404).json({ message: 'Patient not found.' });
70
+ }
71
+
72
+ await pool.query(
73
+ `UPDATE patients SET full_name = ?, gender = ?, date_of_birth = ?,
74
+ phone_number = ?, address = ? WHERE id = ?`,
75
+ [full_name, gender, date_of_birth, phone_number, address, req.params.id]
76
+ );
77
+
78
+ const [patient] = await pool.query('SELECT * FROM patients WHERE id = ?', [
79
+ req.params.id,
80
+ ]);
81
+ res.json(patient[0]);
82
+ } catch (err) {
83
+ console.error(err);
84
+ res.status(500).json({ message: 'Failed to update patient.' });
85
+ }
86
+ });
87
+
88
+ router.delete('/:id', async (req, res) => {
89
+ try {
90
+ const [result] = await pool.query('DELETE FROM patients WHERE id = ?', [
91
+ req.params.id,
92
+ ]);
93
+ if (result.affectedRows === 0) {
94
+ return res.status(404).json({ message: 'Patient not found.' });
95
+ }
96
+ res.json({ message: 'Patient deleted successfully.' });
97
+ } catch (err) {
98
+ console.error(err);
99
+ res.status(500).json({ message: 'Failed to delete patient.' });
100
+ }
101
+ });
102
+
103
+ module.exports = router;
@@ -0,0 +1,60 @@
1
+ const express = require('express');
2
+ const pool = require('../config/db');
3
+ const { authenticate } = require('../middleware/auth');
4
+
5
+ const router = express.Router();
6
+
7
+ router.use(authenticate);
8
+
9
+ router.get('/summary', async (req, res) => {
10
+ try {
11
+ const { start_date, end_date } = req.query;
12
+
13
+ if (!start_date || !end_date) {
14
+ return res.status(400).json({ message: 'Start date and end date are required.' });
15
+ }
16
+
17
+ const [appointments] = await pool.query(
18
+ `SELECT a.*,
19
+ p.full_name AS patient_name,
20
+ u.full_name AS doctor_name
21
+ FROM appointments a
22
+ JOIN patients p ON a.patient_id = p.id
23
+ JOIN users u ON a.doctor_id = u.id
24
+ WHERE a.appointment_date BETWEEN ? AND ?
25
+ ORDER BY a.appointment_date DESC`,
26
+ [start_date, end_date]
27
+ );
28
+
29
+ const [attendedPatients] = await pool.query(
30
+ `SELECT DISTINCT p.id, p.full_name, p.gender, p.date_of_birth,
31
+ p.phone_number, p.address, mr.report_date
32
+ FROM medical_reports mr
33
+ JOIN patients p ON mr.patient_id = p.id
34
+ WHERE mr.report_date BETWEEN ? AND ?
35
+ ORDER BY p.full_name`,
36
+ [start_date, end_date]
37
+ );
38
+
39
+ const total = appointments.length;
40
+ const completed = appointments.filter((a) => a.status === 'completed').length;
41
+ const cancelled = appointments.filter((a) => a.status === 'cancelled').length;
42
+ const scheduled = appointments.filter((a) => a.status === 'scheduled').length;
43
+
44
+ res.json({
45
+ start_date,
46
+ end_date,
47
+ total_appointments: total,
48
+ total_completed: completed,
49
+ total_cancelled: cancelled,
50
+ total_scheduled: scheduled,
51
+ patients_attended: attendedPatients,
52
+ appointments,
53
+ });
54
+ } catch (err) {
55
+ console.error(err);
56
+ res.status(500).json({ message: 'Failed to generate report.' });
57
+ }
58
+ });
59
+
60
+ module.exports = router;
@@ -0,0 +1,38 @@
1
+ const express = require('express');
2
+ const cors = require('cors');
3
+ require('dotenv').config();
4
+
5
+ const authRoutes = require('./routes/auth');
6
+ const patientRoutes = require('./routes/patients');
7
+ const appointmentRoutes = require('./routes/appointments');
8
+ const medicalReportRoutes = require('./routes/medicalReports');
9
+ const reportRoutes = require('./routes/reports');
10
+
11
+ const app = express();
12
+ const PORT = process.env.PORT || 5000;
13
+
14
+ app.use(cors());
15
+ app.use(express.json());
16
+
17
+ app.get('/api/health', (req, res) => {
18
+ res.json({ status: 'ok', message: 'HMS API is running' });
19
+ });
20
+
21
+ app.use('/api/auth', authRoutes);
22
+ app.use('/api/patients', patientRoutes);
23
+ app.use('/api/appointments', appointmentRoutes);
24
+ app.use('/api/medical-reports', medicalReportRoutes);
25
+ app.use('/api/reports', reportRoutes);
26
+
27
+ app.use((req, res) => {
28
+ res.status(404).json({ message: 'Route not found.' });
29
+ });
30
+
31
+ app.use((err, req, res, next) => {
32
+ console.error(err);
33
+ res.status(500).json({ message: 'Internal server error.' });
34
+ });
35
+
36
+ app.listen(PORT, () => {
37
+ console.log(`Server running on http://localhost:${PORT}`);
38
+ });