create-jinmankn-app 1.0.12 → 1.0.13
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/package.json +1 -1
- package/templates/EPMS(Employee Payroll Managment System)/package-lock.json +13 -0
- package/templates/SMS(Stock Managment System)/backend-project/server.js +1 -1
- package/templates/SMS(Stock Managment System)/frontend-project/src/components/AppLayout.jsx +1 -1
- package/templates/SMS(Stock Managment System)/frontend-project/src/pages/Login.jsx +1 -1
- package/templates/SMS(Stock Managment System)/frontend-project/src/pages/Product.jsx +211 -78
- package/templates/SMS(Stock Managment System)/frontend-project/src/pages/Profile.jsx +1 -1
- package/templates/SMS(Stock Managment System)/frontend-project/src/pages/Register.jsx +1 -1
- package/templates/SMS(Stock Managment System)/frontend-project/src/pages/Reports.jsx +1 -1
- package/templates/SMS(Stock Managment System)/frontend-project/src/pages/Sales.jsx +6 -6
- package/templates/SMS(Stock Managment System)/frontend-project/src/pages/Warehouse.jsx +150 -44
- package/templates/SMS(Stock Managment System)/package-lock.json +13 -0
- package/templates/index/README.md +34 -0
- package/templates/index/backend/config/db.js +12 -0
- package/templates/index/backend/controllers/authController.js +88 -0
- package/templates/index/backend/controllers/departmentController.js +74 -0
- package/templates/index/backend/controllers/employeeController.js +204 -0
- package/templates/index/backend/controllers/positionController.js +78 -0
- package/templates/index/backend/controllers/reportController.js +45 -0
- package/templates/index/backend/middleware/auth.js +27 -0
- package/templates/index/backend/models/Department.js +15 -0
- package/templates/index/backend/models/Employee.js +73 -0
- package/templates/index/backend/models/Position.js +20 -0
- package/templates/index/backend/models/User.js +32 -0
- package/templates/index/backend/package-lock.json +2190 -0
- package/templates/index/backend/package.json +22 -0
- package/templates/index/backend/routes/authRoutes.js +11 -0
- package/templates/index/backend/routes/departmentRoutes.js +17 -0
- package/templates/index/backend/routes/employeeRoutes.js +19 -0
- package/templates/index/backend/routes/positionRoutes.js +17 -0
- package/templates/index/backend/routes/protectedRoutes.js +10 -0
- package/templates/index/backend/routes/reportRoutes.js +9 -0
- package/templates/index/backend/server.js +30 -0
- package/templates/index/frontend/README.md +16 -0
- package/templates/index/frontend/eslint.config.js +21 -0
- package/templates/index/frontend/index.html +13 -0
- package/templates/index/frontend/package-lock.json +3095 -0
- package/templates/index/frontend/package.json +31 -0
- package/templates/index/frontend/public/favicon.svg +1 -0
- package/templates/index/frontend/src/App.css +0 -0
- package/templates/index/frontend/src/App.jsx +35 -0
- package/templates/index/frontend/src/assets/hero.png +0 -0
- package/templates/index/frontend/src/components/DashboardLayout.jsx +90 -0
- package/templates/index/frontend/src/components/ProtectedRoute.jsx +9 -0
- package/templates/index/frontend/src/index.css +59 -0
- package/templates/index/frontend/src/main.jsx +11 -0
- package/templates/index/frontend/src/pages/DashboardHome.jsx +58 -0
- package/templates/index/frontend/src/pages/Department.jsx +150 -0
- package/templates/index/frontend/src/pages/Employee.jsx +366 -0
- package/templates/index/frontend/src/pages/Login.jsx +81 -0
- package/templates/index/frontend/src/pages/Position.jsx +169 -0
- package/templates/index/frontend/src/pages/Register.jsx +102 -0
- package/templates/index/frontend/src/pages/Reports.jsx +94 -0
- package/templates/index/frontend/vite.config.js +7 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
const Position = require('../models/Position');
|
|
2
|
+
|
|
3
|
+
exports.addPosition = async (req, res) => {
|
|
4
|
+
try {
|
|
5
|
+
const { posName, requiredQualification } = req.body;
|
|
6
|
+
|
|
7
|
+
if (!posName || !requiredQualification) {
|
|
8
|
+
return res.status(400).json({ message: 'Position name and qualification are required' });
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const existing = await Position.findOne({ posName: posName.trim() });
|
|
12
|
+
if (existing) {
|
|
13
|
+
return res.status(409).json({ message: 'Position already exists' });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const position = await Position.create({
|
|
17
|
+
posName: posName.trim(),
|
|
18
|
+
requiredQualification: requiredQualification.trim(),
|
|
19
|
+
});
|
|
20
|
+
res.status(201).json(position);
|
|
21
|
+
} catch (err) {
|
|
22
|
+
res.status(500).json({ message: err.message });
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
exports.getPositions = async (req, res) => {
|
|
27
|
+
try {
|
|
28
|
+
const positions = await Position.find();
|
|
29
|
+
res.json(positions);
|
|
30
|
+
} catch (err) {
|
|
31
|
+
res.status(500).json({ message: err.message });
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
exports.updatePosition = async (req, res) => {
|
|
36
|
+
try {
|
|
37
|
+
const { posName, requiredQualification } = req.body;
|
|
38
|
+
|
|
39
|
+
if (!posName || !requiredQualification) {
|
|
40
|
+
return res.status(400).json({ message: 'Position name and qualification are required' });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const position = await Position.findById(req.params.id);
|
|
44
|
+
if (!position) {
|
|
45
|
+
return res.status(404).json({ message: 'Position not found' });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const existing = await Position.findOne({
|
|
49
|
+
posName: posName.trim(),
|
|
50
|
+
_id: { $ne: req.params.id },
|
|
51
|
+
});
|
|
52
|
+
if (existing) {
|
|
53
|
+
return res.status(409).json({ message: 'Position already exists' });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
position.posName = posName.trim();
|
|
57
|
+
position.requiredQualification = requiredQualification.trim();
|
|
58
|
+
await position.save();
|
|
59
|
+
|
|
60
|
+
res.json(position);
|
|
61
|
+
} catch (err) {
|
|
62
|
+
res.status(500).json({ message: err.message });
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
exports.deletePosition = async (req, res) => {
|
|
67
|
+
try {
|
|
68
|
+
const position = await Position.findById(req.params.id);
|
|
69
|
+
if (!position) {
|
|
70
|
+
return res.status(404).json({ message: 'Position not found' });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
await Position.findByIdAndDelete(req.params.id);
|
|
74
|
+
res.json({ message: 'Position deleted successfully' });
|
|
75
|
+
} catch (err) {
|
|
76
|
+
res.status(500).json({ message: err.message });
|
|
77
|
+
}
|
|
78
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const Employee = require('../models/Employee');
|
|
2
|
+
|
|
3
|
+
const ON_LEAVE_STATUS = 'on leave';
|
|
4
|
+
|
|
5
|
+
exports.getOnLeaveByDepartment = async (req, res) => {
|
|
6
|
+
try {
|
|
7
|
+
const onLeaveEmployees = await Employee.find({ status: ON_LEAVE_STATUS })
|
|
8
|
+
.populate('department position')
|
|
9
|
+
.sort({ lastName: 1, firstName: 1 });
|
|
10
|
+
|
|
11
|
+
const byDepartment = {};
|
|
12
|
+
|
|
13
|
+
onLeaveEmployees.forEach((employee) => {
|
|
14
|
+
const deptName = employee.department?.departmentName || 'Unassigned';
|
|
15
|
+
if (!byDepartment[deptName]) {
|
|
16
|
+
byDepartment[deptName] = [];
|
|
17
|
+
}
|
|
18
|
+
byDepartment[deptName].push({
|
|
19
|
+
id: employee._id,
|
|
20
|
+
firstName: employee.firstName,
|
|
21
|
+
lastName: employee.lastName,
|
|
22
|
+
email: employee.email,
|
|
23
|
+
telephone: employee.telephone,
|
|
24
|
+
position: employee.position?.posName || 'N/A',
|
|
25
|
+
status: employee.status,
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const departments = Object.keys(byDepartment)
|
|
30
|
+
.sort()
|
|
31
|
+
.map((departmentName) => ({
|
|
32
|
+
departmentName,
|
|
33
|
+
employees: byDepartment[departmentName],
|
|
34
|
+
count: byDepartment[departmentName].length,
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
res.json({
|
|
38
|
+
reportTitle: 'Employee Status Report — On Leave',
|
|
39
|
+
totalOnLeave: onLeaveEmployees.length,
|
|
40
|
+
departments,
|
|
41
|
+
});
|
|
42
|
+
} catch (err) {
|
|
43
|
+
res.status(500).json({ message: err.message });
|
|
44
|
+
}
|
|
45
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
const jwt = require('jsonwebtoken');
|
|
3
|
+
const User = require('../models/User');
|
|
4
|
+
const JWT_SECRET = 'change_this_to_a_long_random_secret';
|
|
5
|
+
|
|
6
|
+
exports.protect = async (req, res, next) => {
|
|
7
|
+
try {
|
|
8
|
+
const header = req.headers.authorization;
|
|
9
|
+
|
|
10
|
+
if (!header || !header.startsWith('Bearer ')) {
|
|
11
|
+
return res.status(401).json({ message: 'Not authorized' });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const token = header.split(' ')[1];
|
|
15
|
+
const decoded = jwt.verify(token, JWT_SECRET);
|
|
16
|
+
const user = await User.findById(decoded.userId).select('-password');
|
|
17
|
+
|
|
18
|
+
if (!user) {
|
|
19
|
+
return res.status(401).json({ message: 'Not authorized' });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
req.user = user;
|
|
23
|
+
next();
|
|
24
|
+
} catch (err) {
|
|
25
|
+
return res.status(401).json({ message: 'Not authorized' });
|
|
26
|
+
}
|
|
27
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
|
|
3
|
+
const departmentSchema = new mongoose.Schema(
|
|
4
|
+
{
|
|
5
|
+
departmentName: {
|
|
6
|
+
type: String,
|
|
7
|
+
required: true,
|
|
8
|
+
unique: true,
|
|
9
|
+
trim: true,
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
{ timestamps: true }
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
module.exports = mongoose.model('Department', departmentSchema);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
|
|
3
|
+
const EMPLOYEE_STATUSES = ['on leave', 'left', 'blacklisted', 'deceased', 'on mission'];
|
|
4
|
+
|
|
5
|
+
const employeeSchema = new mongoose.Schema(
|
|
6
|
+
{
|
|
7
|
+
userName: {
|
|
8
|
+
type: String,
|
|
9
|
+
trim: true,
|
|
10
|
+
},
|
|
11
|
+
firstName: {
|
|
12
|
+
type: String,
|
|
13
|
+
required: true,
|
|
14
|
+
trim: true,
|
|
15
|
+
},
|
|
16
|
+
lastName: {
|
|
17
|
+
type: String,
|
|
18
|
+
required: true,
|
|
19
|
+
trim: true,
|
|
20
|
+
},
|
|
21
|
+
email: {
|
|
22
|
+
type: String,
|
|
23
|
+
required: true,
|
|
24
|
+
unique: true,
|
|
25
|
+
lowercase: true,
|
|
26
|
+
trim: true,
|
|
27
|
+
},
|
|
28
|
+
gender: {
|
|
29
|
+
type: String,
|
|
30
|
+
required: true,
|
|
31
|
+
trim: true,
|
|
32
|
+
},
|
|
33
|
+
dateOfBirth: {
|
|
34
|
+
type: Date,
|
|
35
|
+
required: true,
|
|
36
|
+
},
|
|
37
|
+
telephone: {
|
|
38
|
+
type: String,
|
|
39
|
+
required: true,
|
|
40
|
+
trim: true,
|
|
41
|
+
},
|
|
42
|
+
address: {
|
|
43
|
+
type: String,
|
|
44
|
+
required: true,
|
|
45
|
+
trim: true,
|
|
46
|
+
},
|
|
47
|
+
hireDate: {
|
|
48
|
+
type: Date,
|
|
49
|
+
required: true,
|
|
50
|
+
},
|
|
51
|
+
status: {
|
|
52
|
+
type: String,
|
|
53
|
+
required: true,
|
|
54
|
+
enum: EMPLOYEE_STATUSES,
|
|
55
|
+
default: 'on mission',
|
|
56
|
+
},
|
|
57
|
+
department: {
|
|
58
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
59
|
+
ref: 'Department',
|
|
60
|
+
required: true,
|
|
61
|
+
},
|
|
62
|
+
position: {
|
|
63
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
64
|
+
ref: 'Position',
|
|
65
|
+
required: true,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{ timestamps: true }
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
employeeSchema.statics.STATUSES = EMPLOYEE_STATUSES;
|
|
72
|
+
|
|
73
|
+
module.exports = mongoose.model('Employee', employeeSchema);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
|
|
3
|
+
const positionSchema = new mongoose.Schema(
|
|
4
|
+
{
|
|
5
|
+
posName: {
|
|
6
|
+
type: String,
|
|
7
|
+
required: true,
|
|
8
|
+
unique: true,
|
|
9
|
+
trim: true,
|
|
10
|
+
},
|
|
11
|
+
requiredQualification: {
|
|
12
|
+
type: String,
|
|
13
|
+
required: true,
|
|
14
|
+
trim: true,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
{ timestamps: true }
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
module.exports = mongoose.model('Position', positionSchema);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
|
|
3
|
+
const userSchema = new mongoose.Schema(
|
|
4
|
+
{
|
|
5
|
+
name: {
|
|
6
|
+
type: String,
|
|
7
|
+
required: true,
|
|
8
|
+
trim: true,
|
|
9
|
+
},
|
|
10
|
+
email: {
|
|
11
|
+
type: String,
|
|
12
|
+
required: true,
|
|
13
|
+
unique: true,
|
|
14
|
+
lowercase: true,
|
|
15
|
+
trim: true,
|
|
16
|
+
},
|
|
17
|
+
password: {
|
|
18
|
+
type: String,
|
|
19
|
+
required: true,
|
|
20
|
+
minlength: 6,
|
|
21
|
+
},
|
|
22
|
+
employee: {
|
|
23
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
24
|
+
ref: 'Employee',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
{ timestamps: true }
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const User = mongoose.model('User', userSchema);
|
|
31
|
+
|
|
32
|
+
module.exports = User;
|