create-jinmankn-app 1.0.10 → 1.0.12

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 (115) hide show
  1. package/bin/index.js +38 -80
  2. package/package.json +6 -4
  3. package/templates/EPMS(Employee Payroll Managment System)/backend/routes/protectedRoutes.js +10 -0
  4. package/templates/EPMS(Employee Payroll Managment System)/backend/server.js +2 -0
  5. package/templates/EPMS(Employee Payroll Managment System)/frontend/src/App.jsx +2 -1
  6. package/templates/EPMS(Employee Payroll Managment System)/frontend/src/components/ProtectedRoute.jsx +8 -0
  7. package/templates/Faisal Hospital Managment System (FHMS) mysql/backend/routes/secureRoutes.js +14 -0
  8. package/templates/{hospital-faisal/backend/server.js → Faisal Hospital Managment System (FHMS) mysql/backend/server.js } +2 -0
  9. package/templates/{hospital-faisal/frontend/src/components/ProtectedRoute.jsx → Faisal Hospital Managment System (FHMS) mysql/frontend/src/components/ProtectedRoute.jsx } +2 -3
  10. package/templates/Faisal Hospital Managment System (FHMS) mysql/frontend/src/utils/auth.js +13 -0
  11. package/templates/LMS(Library Managment System)/backend/controllers/authController.js +32 -0
  12. package/templates/LMS(Library Managment System)/backend/routes/authRoutes.js +2 -1
  13. package/templates/LMS(Library Managment System)/backend/routes/protectedRoutes.js +19 -0
  14. package/templates/LMS(Library Managment System)/backend/server.js +2 -0
  15. package/templates/LMS(Library Managment System)/frontend/src/App.jsx +74 -15
  16. package/templates/LMS(Library Managment System)/frontend/src/ProtectedRoute.jsx +13 -0
  17. package/templates/LMS(Library Managment System)/frontend/src/pages/Login.jsx +4 -1
  18. package/templates/LMS(Library Managment System)/frontend/src/pages/Register.jsx +87 -0
  19. package/templates/SCMS(Supply Chain Managment System)/backend/routes/protectedRoutes.js +10 -0
  20. package/templates/SCMS(Supply Chain Managment System)/backend/server.js +2 -0
  21. package/templates/SCMS(Supply Chain Managment System)/frontend/src/App.jsx +2 -1
  22. package/templates/SCMS(Supply Chain Managment System)/frontend/src/components/ProtectedRoute.jsx +30 -0
  23. package/templates/SFM(School Fee Managment)/backend/middleware/protectedRoutes.js +10 -0
  24. package/templates/SFM(School Fee Managment)/frontend/src/App.jsx +7 -5
  25. package/templates/SFM(School Fee Managment)/frontend/src/components/ProtectedRoute.jsx +13 -0
  26. package/templates/SIMS(Stock Inventory Managment System)/backend/controllers/protectedController.js +14 -0
  27. package/templates/SIMS(Stock Inventory Managment System)/backend/routes/protectedRoutes.js +10 -0
  28. package/templates/SIMS(Stock Inventory Managment System)/backend/server.js +2 -1
  29. package/templates/SIMS(Stock Inventory Managment System)/frontend/src/App.jsx +57 -7
  30. package/templates/SIMS(Stock Inventory Managment System)/frontend/src/components/ProtectedRoute.jsx +8 -0
  31. package/templates/SMS(Stock Managment System)/backend-project/routes/protectedRoutes.js +18 -0
  32. package/templates/SMS(Stock Managment System)/backend-project/server.js +2 -0
  33. package/templates/SMS(Stock Managment System)/frontend-project/src/App.jsx +36 -7
  34. package/templates/SMS(Stock Managment System)/frontend-project/src/components/ProtectedRoute.jsx +13 -0
  35. package/templates/SRMS(Sales Record Management System)/backend/routes/protectedRoutes.js +13 -0
  36. package/templates/SRMS(Sales Record Management System)/backend/server.js +2 -0
  37. package/templates/SRMS(Sales Record Management System)/frontend/src/App.jsx +2 -1
  38. package/templates/SRMS(Sales Record Management System)/frontend/src/components/ProtectedRoute.jsx +22 -0
  39. /package/templates/{blueprint → Code blueprint}/BLUEPRINT_REPRODUCTION_PROMPT.md +0 -0
  40. /package/templates/{blueprint → Code blueprint}/HOW_IT_WORKS.md +0 -0
  41. /package/templates/{blueprint → Code blueprint}/README.md +0 -0
  42. /package/templates/{blueprint → Code blueprint}/backend/config/db.js +0 -0
  43. /package/templates/{blueprint → Code blueprint}/backend/controllers/authController.js +0 -0
  44. /package/templates/{blueprint → Code blueprint}/backend/controllers/itemController.js +0 -0
  45. /package/templates/{blueprint → Code blueprint}/backend/middleware/auth.js +0 -0
  46. /package/templates/{blueprint → Code blueprint}/backend/middleware/errorHandler.js +0 -0
  47. /package/templates/{blueprint → Code blueprint}/backend/models/Item.js +0 -0
  48. /package/templates/{blueprint → Code blueprint}/backend/models/User.js +0 -0
  49. /package/templates/{blueprint → Code blueprint}/backend/package-lock.json +0 -0
  50. /package/templates/{blueprint → Code blueprint}/backend/package.json +0 -0
  51. /package/templates/{blueprint → Code blueprint}/backend/routes/authRoutes.js +0 -0
  52. /package/templates/{blueprint → Code blueprint}/backend/routes/healthRoutes.js +0 -0
  53. /package/templates/{blueprint → Code blueprint}/backend/routes/itemRoutes.js +0 -0
  54. /package/templates/{blueprint → Code blueprint}/backend/server.js +0 -0
  55. /package/templates/{blueprint → Code blueprint}/frontend/.env.example +0 -0
  56. /package/templates/{blueprint → Code blueprint}/frontend/index.html +0 -0
  57. /package/templates/{blueprint → Code blueprint}/frontend/package-lock.json +0 -0
  58. /package/templates/{blueprint → Code blueprint}/frontend/package.json +0 -0
  59. /package/templates/{blueprint → Code blueprint}/frontend/public/favicon.svg +0 -0
  60. /package/templates/{blueprint → Code blueprint}/frontend/src/App.jsx +0 -0
  61. /package/templates/{blueprint → Code blueprint}/frontend/src/assets/logo.svg +0 -0
  62. /package/templates/{blueprint → Code blueprint}/frontend/src/components/DashboardLayout.jsx +0 -0
  63. /package/templates/{blueprint → Code blueprint}/frontend/src/components/ProtectedRoute.jsx +0 -0
  64. /package/templates/{blueprint → Code blueprint}/frontend/src/index.css +0 -0
  65. /package/templates/{blueprint → Code blueprint}/frontend/src/main.jsx +0 -0
  66. /package/templates/{blueprint → Code blueprint}/frontend/src/pages/DashboardHome.jsx +0 -0
  67. /package/templates/{blueprint → Code blueprint}/frontend/src/pages/Items.jsx +0 -0
  68. /package/templates/{blueprint → Code blueprint}/frontend/src/pages/Login.jsx +0 -0
  69. /package/templates/{blueprint → Code blueprint}/frontend/src/pages/Profile.jsx +0 -0
  70. /package/templates/{blueprint → Code blueprint}/frontend/src/pages/Register.jsx +0 -0
  71. /package/templates/{blueprint → Code blueprint}/frontend/src/pages/Report.jsx +0 -0
  72. /package/templates/{blueprint → Code blueprint}/frontend/vite.config.js +0 -0
  73. /package/templates/{blueprint → Code blueprint}/package.json +0 -0
  74. /package/templates/{blueprint → Code blueprint}/scripts/pack-blueprint.ps1 +0 -0
  75. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/.env.example +0 -0
  76. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/config/db.js +0 -0
  77. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/controllers/appointmentController.js +0 -0
  78. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/controllers/authController.js +0 -0
  79. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/controllers/hospitalReportController.js +0 -0
  80. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/controllers/medicalReportController.js +0 -0
  81. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/controllers/patientController.js +0 -0
  82. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/database/schema.sql +0 -0
  83. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/middleware/auth.js +0 -0
  84. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/middleware/errorHandler.js +0 -0
  85. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/middleware/role.js +0 -0
  86. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/package-lock.json +0 -0
  87. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/package.json +0 -0
  88. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/routes/appointmentRoutes.js +0 -0
  89. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/routes/authRoutes.js +0 -0
  90. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/routes/healthRoutes.js +0 -0
  91. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/routes/hospitalReportRoutes.js +0 -0
  92. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/routes/medicalReportRoutes.js +0 -0
  93. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/backend/routes/patientRoutes.js +0 -0
  94. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/.env.example +0 -0
  95. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/index.html +0 -0
  96. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/package-lock.json +0 -0
  97. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/package.json +0 -0
  98. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/public/favicon.svg +0 -0
  99. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/src/App.jsx +0 -0
  100. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/src/api.js +0 -0
  101. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/src/assets/logo.svg +0 -0
  102. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/src/components/DashboardLayout.jsx +0 -0
  103. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/src/components/RoleRoute.jsx +0 -0
  104. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/src/index.css +0 -0
  105. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/src/main.jsx +0 -0
  106. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/src/pages/Appointments.jsx +0 -0
  107. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/src/pages/DashboardHome.jsx +0 -0
  108. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/src/pages/Login.jsx +0 -0
  109. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/src/pages/MedicalReports.jsx +0 -0
  110. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/src/pages/Patients.jsx +0 -0
  111. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/src/pages/Profile.jsx +0 -0
  112. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/src/pages/Register.jsx +0 -0
  113. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/src/pages/Report.jsx +0 -0
  114. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/frontend/vite.config.js +0 -0
  115. /package/templates/{hospital-faisal → Faisal Hospital Managment System (FHMS) mysql}/package.json +0 -0
package/bin/index.js CHANGED
@@ -1,87 +1,45 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
- import inquirer from "inquirer";
4
- import fs from "fs-extra";
5
- import path from "path";
6
- import ora from "ora";
7
- import chalk from "chalk";
8
- import { fileURLToPath } from "url";
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import fse from 'fs-extra';
6
+ import inquirer from 'inquirer';
7
+ import { fileURLToPath } from 'url';
9
8
 
10
9
  const __filename = fileURLToPath(import.meta.url);
11
10
  const __dirname = path.dirname(__filename);
12
11
 
13
- const templatesDir = path.join(__dirname, "../templates");
14
-
15
- // 🔒 Check templates folder exists
16
- if (!fs.existsSync(templatesDir)) {
17
- console.log(chalk.red("Templates folder not found!"));
18
- process.exit(1);
19
- }
20
-
21
- // 📦 Get templates (folders only)
22
- const templates = fs
23
- .readdirSync(templatesDir)
24
- .filter((dir) =>
25
- fs.lstatSync(path.join(templatesDir, dir)).isDirectory()
26
- );
27
-
28
- // 🔒 No templates check
29
- if (templates.length === 0) {
30
- console.log(chalk.red("❌ No templates found!"));
31
- process.exit(1);
32
- }
33
-
34
- // 🎯 Prompt user
35
- const answers = await inquirer.prompt([
36
- {
37
- type: "input",
38
- name: "projectName",
39
- message: "Project name:"
40
- },
41
- {
42
- type: "list",
43
- name: "template",
44
- message: "Choose a template:",
45
- choices: templates.map((t) => ({
46
- name: `${t}`,
47
- value: t
48
- }))
49
- }
50
- ]);
51
-
52
- const projectPath = path.join(
53
- process.cwd(),
54
- answers.projectName
55
- );
56
-
57
- const templatePath = path.join(
58
- templatesDir,
59
- answers.template
60
- );
61
-
62
- // 🔒 Prevent overwrite
63
- if (fs.existsSync(projectPath)) {
64
- console.log(chalk.red("Folder already exists!"));
65
- process.exit(1);
12
+ async function run() {
13
+ const templatesDir = path.join(__dirname, '../templates');
14
+
15
+ const projects = fs.readdirSync(templatesDir)
16
+ .filter(item =>
17
+ fs.statSync(path.join(templatesDir, item)).isDirectory()
18
+ );
19
+
20
+ const { project } = await inquirer.prompt([
21
+ {
22
+ type: 'list',
23
+ name: 'project',
24
+ message: 'Select a project:',
25
+ choices: projects
26
+ }
27
+ ]);
28
+
29
+ const { projectName } = await inquirer.prompt([
30
+ {
31
+ type: 'input',
32
+ name: 'projectName',
33
+ message: 'Enter project name:'
34
+ }
35
+ ]);
36
+
37
+ const source = path.join(templatesDir, project);
38
+ const destination = path.join(process.cwd(), projectName);
39
+
40
+ await fse.copy(source, destination);
41
+
42
+ console.log(`✅ Project "${projectName}" created successfully!`);
66
43
  }
67
44
 
68
- // 🚀 Spinner
69
- const spinner = ora("Creating project...").start();
70
-
71
- try {
72
- // 📂 Copy template into new folder
73
- await fs.copy(templatePath, projectPath);
74
-
75
- spinner.succeed(
76
- chalk.green("Project created successfully!")
77
- );
78
-
79
- console.log("\n");
80
- console.log(chalk.cyan("Next steps:"));
81
- console.log(chalk.white(`cd ${answers.projectName}`));
82
- console.log(chalk.white("npm install"));
83
- console.log(chalk.white("npm run dev"));
84
- } catch (err) {
85
- spinner.fail(chalk.red("Failed to create project"));
86
- console.log(err);
87
- }
45
+ run().catch(console.error);
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "create-jinmankn-app",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "create-jinmankn-app": "./bin/index.js"
7
- },"scripts": {
7
+ },
8
+ "scripts": {
8
9
  "pub": "npm version patch -m \"release: %s\" && npm publish --access public"
9
10
  },
10
11
  "files": [
@@ -21,9 +22,10 @@
21
22
  ],
22
23
  "license": "MIT",
23
24
  "dependencies": {
25
+ "axios": "^1.16.1",
24
26
  "chalk": "^5.6.0",
25
- "fs-extra": "^11.3.1",
26
- "inquirer": "^12.9.4",
27
+ "fs-extra": "^11.3.5",
28
+ "inquirer": "^12.11.1",
27
29
  "ora": "^9.0.0"
28
30
  }
29
31
  }
@@ -0,0 +1,10 @@
1
+ const express = require('express');
2
+ const router = express.Router();
3
+ const { protect } = require('../middleware/auth');
4
+
5
+ // Simple protected endpoint that returns the authenticated user
6
+ router.get('/', protect, (req, res) => {
7
+ res.json({ message: 'This is a protected route', user: req.user });
8
+ });
9
+
10
+ module.exports = router;
@@ -7,6 +7,7 @@ const authRoutes = require('./routes/authRoutes');
7
7
  const departmentRoutes = require('./routes/departmentRoutes');
8
8
  const employeeRoutes = require('./routes/employeeRoutes');
9
9
  const salaryRoutes = require('./routes/salaryRoutes');
10
+ const protectedRoutes = require('./routes/protectedRoutes');
10
11
 
11
12
  const app = express();
12
13
 
@@ -18,6 +19,7 @@ app.use('/api/auth', authRoutes);
18
19
  app.use('/api/departments', departmentRoutes);
19
20
  app.use('/api/employees', employeeRoutes);
20
21
  app.use('/api/salaries', salaryRoutes);
22
+ app.use('/api/protected', protectedRoutes);
21
23
 
22
24
  const PORT = 5001;
23
25
  app.listen(PORT, () => {
@@ -1,5 +1,6 @@
1
1
  import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
2
2
  import DashboardLayout from './components/DashboardLayout';
3
+ import ProtectedRoute from './components/ProtectedRoute';
3
4
  import DashboardHome from './pages/DashboardHome';
4
5
  import Register from './pages/Register';
5
6
  import Login from './pages/Login';
@@ -16,7 +17,7 @@ function App() {
16
17
  <Route path="/login" element={<Login />} />
17
18
  <Route path="/register" element={<Register />} />
18
19
 
19
- <Route path="/dashboard" element={<DashboardLayout />}>
20
+ <Route path="/dashboard" element={<ProtectedRoute><DashboardLayout /></ProtectedRoute>}>
20
21
  <Route index element={<DashboardHome />} />
21
22
  <Route path="department" element={<Department />} />
22
23
  <Route path="employee" element={<Employee />} />
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { Navigate } from 'react-router-dom';
3
+
4
+ export default function ProtectedRoute({ children }) {
5
+ const token = localStorage.getItem('token');
6
+ if (!token) return <Navigate to="/login" replace />;
7
+ return children;
8
+ }
@@ -0,0 +1,14 @@
1
+ const express = require('express');
2
+ const { protect } = require('../middleware/auth');
3
+
4
+ const router = express.Router();
5
+
6
+ // A simple protected route for testing auth-protected access.
7
+ router.get('/', protect, (req, res) => {
8
+ res.json({
9
+ message: 'Protected route accessed successfully',
10
+ user: req.user,
11
+ });
12
+ });
13
+
14
+ module.exports = router;
@@ -3,6 +3,7 @@ const express = require('express');
3
3
  const cors = require('cors');
4
4
  const { initDatabase } = require('./config/db');
5
5
  const authRoutes = require('./routes/authRoutes');
6
+ const secureRoutes = require('./routes/secureRoutes');
6
7
  const patientRoutes = require('./routes/patientRoutes');
7
8
  const appointmentRoutes = require('./routes/appointmentRoutes');
8
9
  const medicalReportRoutes = require('./routes/medicalReportRoutes');
@@ -21,6 +22,7 @@ app.use(express.json());
21
22
 
22
23
  app.use('/api/health', healthRoutes);
23
24
  app.use('/api/auth', authRoutes);
25
+ app.use('/api/secure', secureRoutes);
24
26
  app.use('/api/patients', patientRoutes);
25
27
  app.use('/api/appointments', appointmentRoutes);
26
28
  app.use('/api/medical-reports', medicalReportRoutes);
@@ -1,14 +1,13 @@
1
1
  // this component is helping us to protect our routes so that only authenticated users can access the routes
2
2
  import { Navigate } from 'react-router-dom';
3
+ import { isAuthenticated } from '../utils/auth';
3
4
 
4
5
  // this function is firstly checking if the user is authenticated by checking the token in the localStorage
5
6
  // if the user is not authenticated, it will redirect the user to the login page
6
7
  // if the user is authenticated, it will return the children components
7
8
  //and the children component is the component that we want to protect
8
9
  function ProtectedRoute({ children }) {
9
- const token = localStorage.getItem('token');
10
-
11
- if (!token) {
10
+ if (!isAuthenticated()) {
12
11
  return <Navigate to="/login" replace />;
13
12
  }
14
13
 
@@ -0,0 +1,13 @@
1
+ export const getToken = () => localStorage.getItem('token');
2
+
3
+ export const isAuthenticated = () => Boolean(getToken());
4
+
5
+ export const setAuthToken = (token) => {
6
+ if (token) {
7
+ localStorage.setItem('token', token);
8
+ }
9
+ };
10
+
11
+ export const logout = () => {
12
+ localStorage.removeItem('token');
13
+ };
@@ -54,3 +54,35 @@ exports.getMe = async (req, res) => {
54
54
  res.status(500).json({ message: err.message });
55
55
  }
56
56
  };
57
+
58
+ exports.register = async (req, res) => {
59
+ try {
60
+ const { name, username, password } = req.body;
61
+
62
+ if (!name || !username || !password) {
63
+ return res.status(400).json({ message: 'Name, username and password are required' });
64
+ }
65
+
66
+ const existing = await User.findOne({ username: username.toLowerCase() });
67
+ if (existing) {
68
+ return res.status(409).json({ message: 'Username already exists' });
69
+ }
70
+
71
+ const hashed = await bcrypt.hash(password, 10);
72
+
73
+ const user = new User({
74
+ name,
75
+ username: username.toLowerCase(),
76
+ password: hashed,
77
+ role: 'staff',
78
+ });
79
+
80
+ await user.save();
81
+
82
+ const token = createToken(user._id);
83
+
84
+ res.status(201).json({ token, user: formatUser(user) });
85
+ } catch (err) {
86
+ res.status(500).json({ message: err.message });
87
+ }
88
+ };
@@ -1,9 +1,10 @@
1
1
  const express = require('express');
2
- const { login, getMe } = require('../controllers/authController');
2
+ const { login, getMe, register } = require('../controllers/authController');
3
3
  const { protect } = require('../middleware/auth');
4
4
 
5
5
  const router = express.Router();
6
6
 
7
+ router.post('/register', register);
7
8
  router.post('/login', login);
8
9
  router.get('/me', protect, getMe);
9
10
 
@@ -0,0 +1,19 @@
1
+ const express = require('express');
2
+ const { protect } = require('../middleware/auth');
3
+
4
+ const router = express.Router();
5
+
6
+ // Simple protected route for verifying the JWT middleware works
7
+ router.get('/check', protect, (req, res) => {
8
+ res.json({
9
+ message: 'Protected route is working',
10
+ user: {
11
+ id: req.user._id,
12
+ name: req.user.name,
13
+ username: req.user.username,
14
+ role: req.user.role,
15
+ },
16
+ });
17
+ });
18
+
19
+ module.exports = router;
@@ -9,6 +9,7 @@ const bookRoutes = require('./routes/bookRoutes')
9
9
  const studentRoutes = require('./routes/studentRoutes')
10
10
  const searchRoutes = require('./routes/searchRoutes')
11
11
  const statsRoutes = require('./routes/statsRoutes')
12
+ const protectedRoutes = require('./routes/protectedRoutes')
12
13
 
13
14
 
14
15
  const app = express();
@@ -23,6 +24,7 @@ app.use('/api/auth/', authRoutes)
23
24
  app.use('/api/borrow',borrowRoutes)
24
25
  app.use('/api/search', searchRoutes)
25
26
  app.use('/api/stats', statsRoutes)
27
+ app.use('/api/protected', protectedRoutes)
26
28
 
27
29
 
28
30
  const PORT = 5001;
@@ -1,4 +1,5 @@
1
1
  import Login from './pages/Login';
2
+ import Register from './pages/Register';
2
3
  import Dashboard from './components/Dashboard';
3
4
  import Profile from './pages/Profile';
4
5
  import Books from './pages/Books';
@@ -6,6 +7,7 @@ import Borrow from './pages/Borrow';
6
7
  import Return from './pages/Return';
7
8
  import Search from './pages/Search';
8
9
  import Reports from './pages/Reports';
10
+ import ProtectedRoute from './ProtectedRoute';
9
11
 
10
12
  import { BrowserRouter, Routes, Route } from 'react-router-dom';
11
13
  import Students from './pages/Students';
@@ -16,23 +18,80 @@ function App() {
16
18
 
17
19
  return (
18
20
  <div>
19
- <BrowserRouter>
20
- <Routes>
21
- <Route path='/' element={<Login/>}/>
21
+ <BrowserRouter>
22
+ <Routes>
23
+ <Route path='/' element={<Login />} />
24
+ <Route path='/login' element={<Login />} />
25
+ <Route path='/register' element={<Register />} />
22
26
 
23
- <Route path='/dashboard' element={<Dashboard/>}/>
24
- <Route path='/login' element={<Login/>}/>
25
- <Route path='/dashboard/books' element={<Books/>}/>
26
- <Route path='/dashboard/students' element={<Students/>}/>
27
- <Route path='/dashboard/profile' element={<Profile/>}/>
28
- <Route path="/dashboard/borrow" element={<Borrow/>}/>
29
- <Route path="/dashboard/return" element={<Return/>}/>
30
- <Route path="/dashboard/search" element={<Search/>}/>
31
- <Route path="/dashboard/reports" element={<Reports/>}/>
32
- </Routes>
33
- </BrowserRouter>
27
+ <Route
28
+ path='/dashboard'
29
+ element={
30
+ <ProtectedRoute>
31
+ <Dashboard />
32
+ </ProtectedRoute>
33
+ }
34
+ />
35
+ <Route
36
+ path='/dashboard/books'
37
+ element={
38
+ <ProtectedRoute>
39
+ <Books />
40
+ </ProtectedRoute>
41
+ }
42
+ />
43
+ <Route
44
+ path='/dashboard/students'
45
+ element={
46
+ <ProtectedRoute>
47
+ <Students />
48
+ </ProtectedRoute>
49
+ }
50
+ />
51
+ <Route
52
+ path='/dashboard/profile'
53
+ element={
54
+ <ProtectedRoute>
55
+ <Profile />
56
+ </ProtectedRoute>
57
+ }
58
+ />
59
+ <Route
60
+ path='/dashboard/borrow'
61
+ element={
62
+ <ProtectedRoute>
63
+ <Borrow />
64
+ </ProtectedRoute>
65
+ }
66
+ />
67
+ <Route
68
+ path='/dashboard/return'
69
+ element={
70
+ <ProtectedRoute>
71
+ <Return />
72
+ </ProtectedRoute>
73
+ }
74
+ />
75
+ <Route
76
+ path='/dashboard/search'
77
+ element={
78
+ <ProtectedRoute>
79
+ <Search />
80
+ </ProtectedRoute>
81
+ }
82
+ />
83
+ <Route
84
+ path='/dashboard/reports'
85
+ element={
86
+ <ProtectedRoute>
87
+ <Reports />
88
+ </ProtectedRoute>
89
+ }
90
+ />
91
+ </Routes>
92
+ </BrowserRouter>
34
93
  </div>
35
- )
94
+ );
36
95
  }
37
96
 
38
97
  export default App
@@ -0,0 +1,13 @@
1
+ import { Navigate } from 'react-router-dom';
2
+
3
+ function ProtectedRoute({ children }) {
4
+ const token = localStorage.getItem('token');
5
+
6
+ if (!token) {
7
+ return <Navigate to="/login" replace />;
8
+ }
9
+
10
+ return children;
11
+ }
12
+
13
+ export default ProtectedRoute;
@@ -1,6 +1,6 @@
1
1
  import { useState } from 'react';
2
2
  import axios from 'axios';
3
- import { useNavigate } from 'react-router-dom';
3
+ import { useNavigate, Link } from 'react-router-dom';
4
4
 
5
5
  function Login() {
6
6
  const navigate = useNavigate();
@@ -70,6 +70,9 @@ function Login() {
70
70
  <p className="mt-4 text-center text-xs text-slate-500">
71
71
  Default: admin / admin123 or librarian / lib123
72
72
  </p>
73
+ <p className="mt-2 text-center text-xs">
74
+ Don't have an account? <Link to="/register" className="text-blue-400 underline">Create one</Link>
75
+ </p>
73
76
  </div>
74
77
  </div>
75
78
  );
@@ -0,0 +1,87 @@
1
+ import { useState } from 'react';
2
+ import axios from 'axios';
3
+ import { useNavigate, Link } from 'react-router-dom';
4
+
5
+ function Register() {
6
+ const navigate = useNavigate();
7
+ const [name, setName] = useState('');
8
+ const [username, setUsername] = useState('');
9
+ const [password, setPassword] = useState('');
10
+ const [error, setError] = useState('');
11
+ const [loading, setLoading] = useState(false);
12
+
13
+ const handleSubmit = async (e) => {
14
+ e.preventDefault();
15
+ setError('');
16
+ setLoading(true);
17
+
18
+ try {
19
+ const response = await axios.post('http://localhost:5001/api/auth/register', { name, username, password });
20
+ localStorage.setItem('token', response.data.token);
21
+ localStorage.setItem('user', JSON.stringify(response.data.user));
22
+ navigate('/dashboard');
23
+ } catch (err) {
24
+ setError(err.response?.data?.message || 'Registration failed');
25
+ console.error(err.response?.data || err.message);
26
+ } finally {
27
+ setLoading(false);
28
+ }
29
+ };
30
+
31
+ return (
32
+ <div className="flex min-h-screen items-center justify-center px-4">
33
+ <div className="lms-card w-full max-w-md p-8 shadow-lg">
34
+ <p className="text-xs font-semibold uppercase tracking-wider text-slate-400">Library LMS</p>
35
+ <h1 className="mt-1 mb-6 text-2xl font-semibold text-white">Register staff</h1>
36
+
37
+ {error && <p className="lms-alert-error">{error}</p>}
38
+
39
+ <form onSubmit={handleSubmit} className="space-y-4">
40
+ <div>
41
+ <label className="lms-label">Name</label>
42
+ <input
43
+ type="text"
44
+ required
45
+ value={name}
46
+ onChange={(e) => setName(e.target.value)}
47
+ className="lms-input"
48
+ />
49
+ </div>
50
+
51
+ <div>
52
+ <label className="lms-label">Username</label>
53
+ <input
54
+ type="text"
55
+ required
56
+ value={username}
57
+ onChange={(e) => setUsername(e.target.value)}
58
+ className="lms-input"
59
+ />
60
+ </div>
61
+
62
+ <div>
63
+ <label className="lms-label">Password</label>
64
+ <input
65
+ type="password"
66
+ required
67
+ value={password}
68
+ onChange={(e) => setPassword(e.target.value)}
69
+ className="lms-input"
70
+ />
71
+ </div>
72
+
73
+ <button type="submit" disabled={loading} className="lms-btn-primary w-full">
74
+ {loading ? 'Creating account...' : 'Create account'}
75
+ </button>
76
+ </form>
77
+
78
+ <p className="mt-4 text-center text-xs text-slate-500">After registering you will be taken to the dashboard.</p>
79
+ <p className="mt-2 text-center text-xs">
80
+ Already have an account? <Link to="/login" className="text-blue-400 underline">Sign in</Link>
81
+ </p>
82
+ </div>
83
+ </div>
84
+ );
85
+ }
86
+
87
+ export default Register;
@@ -0,0 +1,10 @@
1
+ const express = require('express');
2
+ const router = express.Router();
3
+ const { protect } = require('../middleware/auth');
4
+
5
+ // GET /api/protected - simple protected endpoint
6
+ router.get('/', protect, (req, res) => {
7
+ res.json({ message: 'Protected content', user: req.user });
8
+ });
9
+
10
+ module.exports = router;
@@ -10,6 +10,7 @@ const SupplierRoutes = require('./routes/SupplierRoutes');
10
10
  const shipmentRoutes = require('./routes/shipmentRoutes');
11
11
  const deliveryRoutes = require('./routes/deliveryRoutes');
12
12
  const reportsRoutes = require('./routes/reportsRoutes');
13
+ const protectedRoutes = require('./routes/protectedRoutes');
13
14
 
14
15
  const app = express();
15
16
 
@@ -24,6 +25,7 @@ app.use('/api/sales', salesRoutes);
24
25
  app.use('/api/shipment', shipmentRoutes);
25
26
  app.use('/api/delivery', deliveryRoutes);
26
27
  app.use('/api/reports', reportsRoutes);
28
+ app.use('/api/protected', protectedRoutes);
27
29
 
28
30
  const PORT = 5001;
29
31
  app.listen(PORT, () => {
@@ -8,6 +8,7 @@ import Supplier from './pages/Supplier';
8
8
  import Shipment from './pages/Shipment';
9
9
  import Delivery from './pages/Delivery';
10
10
  import Reports from './pages/Reports';
11
+ import ProtectedRoute from './components/ProtectedRoute';
11
12
 
12
13
  function App() {
13
14
  return (
@@ -16,7 +17,7 @@ function App() {
16
17
  <Route path="/login" element={<Login />} />
17
18
  <Route path="/register" element={<Register />} />
18
19
 
19
- <Route path="/dashboard" element={<DashboardLayout />}>
20
+ <Route path="/dashboard" element={<ProtectedRoute><DashboardLayout /></ProtectedRoute>}>
20
21
  <Route index element={<DashboardHome />} />
21
22
  <Route path="supplier" element={<Supplier />} />
22
23
  <Route path="shipment" element={<Shipment />} />
@@ -0,0 +1,30 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { Navigate } from 'react-router-dom';
3
+
4
+ export default function ProtectedRoute({ children }) {
5
+ const [loading, setLoading] = useState(true);
6
+ const [authorized, setAuthorized] = useState(false);
7
+
8
+ useEffect(() => {
9
+ const token = localStorage.getItem('token');
10
+ if (!token) {
11
+ setLoading(false);
12
+ setAuthorized(false);
13
+ return;
14
+ }
15
+
16
+ fetch('http://localhost:5001/api/protected', {
17
+ headers: { Authorization: `Bearer ${token}` },
18
+ })
19
+ .then((res) => {
20
+ if (res.ok) setAuthorized(true);
21
+ else setAuthorized(false);
22
+ })
23
+ .catch(() => setAuthorized(false))
24
+ .finally(() => setLoading(false));
25
+ }, []);
26
+
27
+ if (loading) return <div>Loading...</div>;
28
+ if (!authorized) return <Navigate to="/login" replace />;
29
+ return children;
30
+ }