create-cedro-app 1.0.2 → 1.0.3
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/bin/index.js +32 -18
- package/package.json +1 -1
- package/templates/invoice-service-management-system/client/README.md +16 -0
- package/templates/invoice-service-management-system/client/eslint.config.js +21 -0
- package/templates/invoice-service-management-system/client/index.html +13 -0
- package/templates/invoice-service-management-system/client/package.json +35 -0
- package/templates/invoice-service-management-system/client/public/favicon.svg +1 -0
- package/templates/invoice-service-management-system/client/public/icons.svg +24 -0
- package/templates/invoice-service-management-system/client/src/App.jsx +15 -0
- package/templates/invoice-service-management-system/client/src/assets/hero.png +0 -0
- package/templates/invoice-service-management-system/client/src/assets/react.svg +1 -0
- package/templates/invoice-service-management-system/client/src/assets/vite.svg +1 -0
- package/templates/invoice-service-management-system/client/src/components/AppRoutes.jsx +39 -0
- package/templates/invoice-service-management-system/client/src/components/Customer.jsx +326 -0
- package/templates/invoice-service-management-system/client/src/components/Dashboard.jsx +512 -0
- package/templates/invoice-service-management-system/client/src/components/Invoice.jsx +523 -0
- package/templates/invoice-service-management-system/client/src/components/Login.jsx +170 -0
- package/templates/invoice-service-management-system/client/src/components/PageNotFound.jsx +11 -0
- package/templates/invoice-service-management-system/client/src/components/Register.jsx +171 -0
- package/templates/invoice-service-management-system/client/src/components/Report.jsx +383 -0
- package/templates/invoice-service-management-system/client/src/components/Service.jsx +390 -0
- package/templates/invoice-service-management-system/client/src/index.css +1 -0
- package/templates/invoice-service-management-system/client/src/main.jsx +13 -0
- package/templates/invoice-service-management-system/client/vite.config.js +9 -0
- package/templates/invoice-service-management-system/server/.env +8 -0
- package/templates/invoice-service-management-system/server/Functions/Customer.js +79 -0
- package/templates/invoice-service-management-system/server/Functions/Invoice.js +192 -0
- package/templates/invoice-service-management-system/server/Functions/Service.js +86 -0
- package/templates/invoice-service-management-system/server/Functions/dashboard.js +33 -0
- package/templates/invoice-service-management-system/server/Functions/report.js +50 -0
- package/templates/invoice-service-management-system/server/Functions/users.js +101 -0
- package/templates/invoice-service-management-system/server/db.js +22 -0
- package/templates/invoice-service-management-system/server/package.json +23 -0
- package/templates/invoice-service-management-system/server/server.js +294 -0
- package/templates/slot-car-management-system/client/README.md +16 -0
- package/templates/slot-car-management-system/client/eslint.config.js +21 -0
- package/templates/slot-car-management-system/client/index.html +13 -0
- package/templates/slot-car-management-system/client/package.json +35 -0
- package/templates/slot-car-management-system/client/public/favicon.svg +1 -0
- package/templates/slot-car-management-system/client/public/icons.svg +24 -0
- package/templates/slot-car-management-system/client/src/App.css +184 -0
- package/templates/slot-car-management-system/client/src/App.jsx +49 -0
- package/templates/slot-car-management-system/client/src/assets/hero.png +0 -0
- package/templates/slot-car-management-system/client/src/assets/react.svg +1 -0
- package/templates/slot-car-management-system/client/src/assets/vite.svg +1 -0
- package/templates/slot-car-management-system/client/src/components/Cars.jsx +246 -0
- package/templates/slot-car-management-system/client/src/components/Dashboard.jsx +629 -0
- package/templates/slot-car-management-system/client/src/components/Login.jsx +170 -0
- package/templates/slot-car-management-system/client/src/components/PageNotFound.jsx +11 -0
- package/templates/slot-car-management-system/client/src/components/ParkingRecord.jsx +553 -0
- package/templates/slot-car-management-system/client/src/components/ParkingSlot.jsx +268 -0
- package/templates/slot-car-management-system/client/src/components/Payment.jsx +464 -0
- package/templates/slot-car-management-system/client/src/components/Register.jsx +171 -0
- package/templates/slot-car-management-system/client/src/components/Report.jsx +407 -0
- package/templates/slot-car-management-system/client/src/index.css +1 -0
- package/templates/slot-car-management-system/client/src/main.jsx +10 -0
- package/templates/slot-car-management-system/client/vite.config.js +9 -0
- package/templates/slot-car-management-system/parking_slot.sql +218 -0
- package/templates/slot-car-management-system/server/.env +8 -0
- package/templates/slot-car-management-system/server/Functions/Payment.js +107 -0
- package/templates/slot-car-management-system/server/Functions/car.js +93 -0
- package/templates/slot-car-management-system/server/Functions/dashboard.js +64 -0
- package/templates/slot-car-management-system/server/Functions/parkingRecord.js +220 -0
- package/templates/slot-car-management-system/server/Functions/parkingslot.js +58 -0
- package/templates/slot-car-management-system/server/Functions/report.js +48 -0
- package/templates/slot-car-management-system/server/Functions/users.js +101 -0
- package/templates/slot-car-management-system/server/db.js +22 -0
- package/templates/slot-car-management-system/server/package.json +23 -0
- package/templates/slot-car-management-system/server/server.js +192 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import db from "../db.js";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export const insertService = (req, res) => {
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
ServiceCode,
|
|
8
|
+
ServiceName,
|
|
9
|
+
ServiceCost,
|
|
10
|
+
TotalDeduction
|
|
11
|
+
} = req.body;
|
|
12
|
+
|
|
13
|
+
// VALIDATION
|
|
14
|
+
if (
|
|
15
|
+
!ServiceCode ||
|
|
16
|
+
!ServiceName ||
|
|
17
|
+
!ServiceCost ||
|
|
18
|
+
!TotalDeduction
|
|
19
|
+
) {
|
|
20
|
+
return res.status(400).json({
|
|
21
|
+
Error: "All fields are required"
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const sql = `
|
|
26
|
+
INSERT INTO service
|
|
27
|
+
(
|
|
28
|
+
ServiceCode,
|
|
29
|
+
ServiceName,
|
|
30
|
+
ServiceCost,
|
|
31
|
+
TotalDeduction
|
|
32
|
+
)
|
|
33
|
+
VALUES (?, ?, ?, ?)
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
db.query(
|
|
37
|
+
sql,
|
|
38
|
+
[
|
|
39
|
+
ServiceCode,
|
|
40
|
+
ServiceName,
|
|
41
|
+
ServiceCost,
|
|
42
|
+
TotalDeduction
|
|
43
|
+
],
|
|
44
|
+
(err, result) => {
|
|
45
|
+
|
|
46
|
+
if (err) {
|
|
47
|
+
|
|
48
|
+
return res.status(500).json({
|
|
49
|
+
Error: `Failed to insert service ${err.message}`
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
res.status(201).json({
|
|
54
|
+
Message: "Service inserted successfully"
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
export const selectServices = (req, res) => {
|
|
62
|
+
|
|
63
|
+
const sql = `
|
|
64
|
+
SELECT * FROM service
|
|
65
|
+
`;
|
|
66
|
+
|
|
67
|
+
db.query(sql, (err, result) => {
|
|
68
|
+
|
|
69
|
+
if (err) {
|
|
70
|
+
|
|
71
|
+
return res.status(500).json({
|
|
72
|
+
Error: `Failed to fetch services ${err.message}`
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (result.length === 0) {
|
|
77
|
+
|
|
78
|
+
return res.status(404).json({
|
|
79
|
+
Error: "No services found"
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
res.status(200).json(result);
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import db from "../db.js";
|
|
2
|
+
|
|
3
|
+
export const dashboardStats = (req, res) => {
|
|
4
|
+
|
|
5
|
+
const sqlCustomer = "SELECT COUNT(*) AS totalCustomers FROM Customer";
|
|
6
|
+
const sqlServices = "SELECT COUNT(*) AS totalServices FROM Service";
|
|
7
|
+
const sqlInvoices = "SELECT COUNT(*) AS totalInvoices FROM Invoice";
|
|
8
|
+
|
|
9
|
+
db.query(sqlCustomer, (err, customersResult) => {
|
|
10
|
+
|
|
11
|
+
if (err) return res.status(500).json({ Error: err.message });
|
|
12
|
+
|
|
13
|
+
db.query(sqlServices, (err, servicesResult) => {
|
|
14
|
+
|
|
15
|
+
if (err) return res.status(500).json({ Error: err.message });
|
|
16
|
+
|
|
17
|
+
db.query(sqlInvoices, (err, invoicesResult) => {
|
|
18
|
+
|
|
19
|
+
if (err) return res.status(500).json({ Error: err.message });
|
|
20
|
+
|
|
21
|
+
return res.status(200).json({
|
|
22
|
+
customers: customersResult[0].totalCustomers,
|
|
23
|
+
services: servicesResult[0].totalServices,
|
|
24
|
+
invoices: invoicesResult[0].totalInvoices
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import db from "../db.js";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export const dailyReport = (req, res) => {
|
|
5
|
+
|
|
6
|
+
const sql = `
|
|
7
|
+
SELECT
|
|
8
|
+
|
|
9
|
+
invoice.InvoiceId,
|
|
10
|
+
customer.FirstName,
|
|
11
|
+
customer.LastName,
|
|
12
|
+
customer.VehiclePlateNumber,
|
|
13
|
+
customer.VehicleType,
|
|
14
|
+
service.ServiceName,
|
|
15
|
+
invoice.TotalCost,
|
|
16
|
+
invoice.PaidAmount,
|
|
17
|
+
invoice.Balance,
|
|
18
|
+
invoice.PaymentMonth
|
|
19
|
+
|
|
20
|
+
FROM invoice
|
|
21
|
+
|
|
22
|
+
JOIN customer
|
|
23
|
+
ON invoice.CustomerId =
|
|
24
|
+
customer.CustomerId
|
|
25
|
+
|
|
26
|
+
JOIN service
|
|
27
|
+
ON invoice.ServiceCode =
|
|
28
|
+
service.ServiceCode
|
|
29
|
+
|
|
30
|
+
ORDER BY invoice.InvoiceId DESC
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
db.query(sql, (err, result) => {
|
|
34
|
+
|
|
35
|
+
if (err) {
|
|
36
|
+
|
|
37
|
+
console.log("REPORT ERROR:", err);
|
|
38
|
+
|
|
39
|
+
return res.status(500).json({
|
|
40
|
+
Error: err.message
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return res.status(200).json({
|
|
45
|
+
message: "Invoice report generated successfully",
|
|
46
|
+
data: result
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
});
|
|
50
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import db from "../db.js";
|
|
2
|
+
import bcrypt from "bcrypt";
|
|
3
|
+
import jwt from "jsonwebtoken";
|
|
4
|
+
import dotenv from "dotenv";
|
|
5
|
+
|
|
6
|
+
dotenv.config();
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
// ============================
|
|
11
|
+
// REGISTER USER
|
|
12
|
+
// ============================
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
// ============================
|
|
21
|
+
// LOGIN USER
|
|
22
|
+
// ============================
|
|
23
|
+
// export const LoginUser = (req, res) => {
|
|
24
|
+
|
|
25
|
+
// const { Email, Password } = req.body;
|
|
26
|
+
|
|
27
|
+
// // VALIDATION
|
|
28
|
+
// if (!Email || !Password) {
|
|
29
|
+
// return res.status(400).json({
|
|
30
|
+
// Error: "Email and password are required"
|
|
31
|
+
// });
|
|
32
|
+
// }
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
// const sql = `
|
|
37
|
+
// SELECT * FROM Users
|
|
38
|
+
// WHERE Email = ?
|
|
39
|
+
// `;
|
|
40
|
+
|
|
41
|
+
// db.query(sql, [Email],async (err, result) => {
|
|
42
|
+
|
|
43
|
+
// if (err) {
|
|
44
|
+
// return res.status(500).json({
|
|
45
|
+
// Error: err.message
|
|
46
|
+
// });
|
|
47
|
+
// }
|
|
48
|
+
|
|
49
|
+
// // USER NOT FOUND
|
|
50
|
+
// if (result.length === 0) {
|
|
51
|
+
// return res.status(404).json({
|
|
52
|
+
// Error: "User not found"
|
|
53
|
+
// });
|
|
54
|
+
// }
|
|
55
|
+
|
|
56
|
+
// const user = result[0];
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
// // COMPARE PASSWORD
|
|
61
|
+
// const isValidPassword = await bcrypt.compare(
|
|
62
|
+
// Password,
|
|
63
|
+
// user.Password
|
|
64
|
+
// );
|
|
65
|
+
|
|
66
|
+
// // INVALID PASSWORD
|
|
67
|
+
// if (!isValidPassword) {
|
|
68
|
+
// return res.status(401).json({
|
|
69
|
+
// Error: "Invalid password"
|
|
70
|
+
// });
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
// // GENERATE TOKEN
|
|
74
|
+
// const token = jwt.sign(
|
|
75
|
+
// {
|
|
76
|
+
// id: user.id,
|
|
77
|
+
// role: user.role
|
|
78
|
+
// },
|
|
79
|
+
// process.env.JWT_SECRET,
|
|
80
|
+
// {
|
|
81
|
+
// expiresIn: "1h"
|
|
82
|
+
// }
|
|
83
|
+
// );
|
|
84
|
+
|
|
85
|
+
// // SUCCESS
|
|
86
|
+
// return res.status(200).json({
|
|
87
|
+
// Message: "Login successful",
|
|
88
|
+
// token,
|
|
89
|
+
// user: {
|
|
90
|
+
// id: user.id,
|
|
91
|
+
// role: user.role
|
|
92
|
+
// }
|
|
93
|
+
// });
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
// }
|
|
97
|
+
|
|
98
|
+
// });
|
|
99
|
+
|
|
100
|
+
// };
|
|
101
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import mysql from 'mysql2'
|
|
2
|
+
|
|
3
|
+
import dotenv from 'dotenv'
|
|
4
|
+
|
|
5
|
+
dotenv.config();
|
|
6
|
+
|
|
7
|
+
let db;
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
db = mysql.createConnection({
|
|
11
|
+
host: process.env.HOST,
|
|
12
|
+
user: process.env.USER,
|
|
13
|
+
password: process.env.PASSWORD,
|
|
14
|
+
database: process.env.DATABASE
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
console.log("connection successfully")
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.error(error)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default db
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "server.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
+
"start": "nodemon server.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [],
|
|
11
|
+
"author": "",
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"bcrypt": "^6.0.0",
|
|
16
|
+
"cors": "^2.8.6",
|
|
17
|
+
"dotenv": "^17.4.2",
|
|
18
|
+
"express": "^5.2.1",
|
|
19
|
+
"jsonwebtoken": "^9.0.3",
|
|
20
|
+
"mysql2": "^3.22.3",
|
|
21
|
+
"nodemon": "^3.1.14"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import cors from "cors";
|
|
3
|
+
import dotenv from "dotenv";
|
|
4
|
+
import bcrypt from "bcrypt";
|
|
5
|
+
import jwt from "jsonwebtoken";
|
|
6
|
+
|
|
7
|
+
import db from "./db.js";
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
insertService,
|
|
12
|
+
selectServices,
|
|
13
|
+
|
|
14
|
+
} from "./Functions/Service.js";
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
createInvoice,
|
|
18
|
+
getAllInvoices,
|
|
19
|
+
getSingleInvoice,
|
|
20
|
+
updateInvoice,
|
|
21
|
+
deleteInvoice
|
|
22
|
+
} from "./Functions/Invoice.js";
|
|
23
|
+
|
|
24
|
+
import { dailyReport } from "./Functions/report.js";
|
|
25
|
+
import { InsertCustomer, SelectCustomers } from "./Functions/Customer.js";
|
|
26
|
+
import { dashboardStats } from "./Functions/dashboard.js";
|
|
27
|
+
|
|
28
|
+
dotenv.config();
|
|
29
|
+
|
|
30
|
+
const app = express();
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
app.use(cors());
|
|
34
|
+
app.use(express.json());
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
function VerifyToken(req, res, next) {
|
|
38
|
+
|
|
39
|
+
const authHeader = req.headers.authorization;
|
|
40
|
+
|
|
41
|
+
if (!authHeader) {
|
|
42
|
+
|
|
43
|
+
return res.status(401).json({
|
|
44
|
+
Error: "No token provided"
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const token = authHeader.split(" ")[1];
|
|
49
|
+
|
|
50
|
+
if (!token) {
|
|
51
|
+
|
|
52
|
+
return res.status(401).json({
|
|
53
|
+
Error: "Invalid token format"
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
jwt.verify(
|
|
58
|
+
token,
|
|
59
|
+
process.env.JWT_SECRET,
|
|
60
|
+
(err, user) => {
|
|
61
|
+
|
|
62
|
+
if (err) {
|
|
63
|
+
|
|
64
|
+
return res.status(403).json({
|
|
65
|
+
Error: `Invalid token ${err.message}`
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
req.user = user;
|
|
70
|
+
|
|
71
|
+
next();
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
app.get("/", (req, res) => {
|
|
78
|
+
|
|
79
|
+
res.json({
|
|
80
|
+
Message: "Vehicle Service Billing Management System API Running"
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
//api for customer
|
|
87
|
+
|
|
88
|
+
app.post('/addcustomer',InsertCustomer)
|
|
89
|
+
app.get('/selectcustomers',SelectCustomers)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
// INSERT SERVICE
|
|
93
|
+
app.post(
|
|
94
|
+
"/insertservice",
|
|
95
|
+
VerifyToken,
|
|
96
|
+
insertService
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
//dashboard
|
|
100
|
+
|
|
101
|
+
app.get('/dashboard-stats',VerifyToken,dashboardStats)
|
|
102
|
+
|
|
103
|
+
// SELECT ALL SERVICES
|
|
104
|
+
app.get(
|
|
105
|
+
"/selectservices",
|
|
106
|
+
VerifyToken,
|
|
107
|
+
selectServices
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
app.post(
|
|
114
|
+
"/insertinvoice",
|
|
115
|
+
VerifyToken,
|
|
116
|
+
createInvoice
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
// SELECT ALL INVOICES
|
|
120
|
+
app.get(
|
|
121
|
+
"/selectinvoices",
|
|
122
|
+
VerifyToken,
|
|
123
|
+
getAllInvoices
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
// SELECT SINGLE INVOICE
|
|
127
|
+
app.get(
|
|
128
|
+
"/selectinvoice/:id",
|
|
129
|
+
VerifyToken,
|
|
130
|
+
getSingleInvoice
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
// UPDATE INVOICE
|
|
134
|
+
app.put(
|
|
135
|
+
"/updateinvoice/:id",
|
|
136
|
+
VerifyToken,
|
|
137
|
+
updateInvoice
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
// DELETE INVOICE
|
|
141
|
+
app.delete(
|
|
142
|
+
"/deleteinvoice/:id",
|
|
143
|
+
VerifyToken,
|
|
144
|
+
deleteInvoice
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
app.get(
|
|
149
|
+
"/report",
|
|
150
|
+
VerifyToken,
|
|
151
|
+
dailyReport
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
app.post("/register", async (req, res) => {
|
|
156
|
+
|
|
157
|
+
const {
|
|
158
|
+
Name,
|
|
159
|
+
Email,
|
|
160
|
+
Password
|
|
161
|
+
} = req.body;
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
if (!Name || !Email || !Password) {
|
|
165
|
+
|
|
166
|
+
return res.status(400).json({
|
|
167
|
+
Error: "All fields are required"
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
const hashedPassword = await bcrypt.hash(
|
|
173
|
+
Password,
|
|
174
|
+
10
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
const sql = `
|
|
178
|
+
INSERT INTO users
|
|
179
|
+
(
|
|
180
|
+
Name,
|
|
181
|
+
Email,
|
|
182
|
+
Password
|
|
183
|
+
)
|
|
184
|
+
VALUES (?, ?, ?)
|
|
185
|
+
`;
|
|
186
|
+
|
|
187
|
+
db.query(
|
|
188
|
+
sql,
|
|
189
|
+
[
|
|
190
|
+
Name,
|
|
191
|
+
Email,
|
|
192
|
+
hashedPassword
|
|
193
|
+
],
|
|
194
|
+
(err, result) => {
|
|
195
|
+
|
|
196
|
+
if (err) {
|
|
197
|
+
|
|
198
|
+
return res.status(500).json({
|
|
199
|
+
Error: err.message
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return res.status(201).json({
|
|
204
|
+
Message: "User registered successfully"
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
app.post("/login", async (req, res) => {
|
|
212
|
+
|
|
213
|
+
const {
|
|
214
|
+
Email,
|
|
215
|
+
Password
|
|
216
|
+
} = req.body;
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
if (!Email || !Password) {
|
|
220
|
+
|
|
221
|
+
return res.status(400).json({
|
|
222
|
+
Error: "All fields are required"
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const sql = `
|
|
227
|
+
SELECT * FROM users
|
|
228
|
+
WHERE Email = ?
|
|
229
|
+
`;
|
|
230
|
+
|
|
231
|
+
db.query(sql, [Email], async (err, users) => {
|
|
232
|
+
|
|
233
|
+
if (err) {
|
|
234
|
+
|
|
235
|
+
return res.status(500).json({
|
|
236
|
+
Error: err.message
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
if (users.length === 0) {
|
|
242
|
+
|
|
243
|
+
return res.status(404).json({
|
|
244
|
+
Error: "User not found"
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const user = users[0];
|
|
249
|
+
|
|
250
|
+
// CHECK PASSWORD
|
|
251
|
+
const validPassword = await bcrypt.compare(
|
|
252
|
+
Password,
|
|
253
|
+
user.Password
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
if (!validPassword) {
|
|
257
|
+
|
|
258
|
+
return res.status(401).json({
|
|
259
|
+
Error: "Invalid password"
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
const token = jwt.sign(
|
|
265
|
+
{
|
|
266
|
+
id: user.id,
|
|
267
|
+
role: user.role
|
|
268
|
+
},
|
|
269
|
+
process.env.JWT_SECRET,
|
|
270
|
+
{
|
|
271
|
+
expiresIn: "1h"
|
|
272
|
+
}
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
return res.status(200).json({
|
|
276
|
+
Message: "Login successful",
|
|
277
|
+
token,
|
|
278
|
+
user: {
|
|
279
|
+
id: user.id,
|
|
280
|
+
role: user.role
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
app.listen(process.env.PORT, () => {
|
|
290
|
+
|
|
291
|
+
console.log(
|
|
292
|
+
`Server running on port ${process.env.PORT}`
|
|
293
|
+
);
|
|
294
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# React + Vite
|
|
2
|
+
|
|
3
|
+
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
|
4
|
+
|
|
5
|
+
Currently, two official plugins are available:
|
|
6
|
+
|
|
7
|
+
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
|
|
8
|
+
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
|
|
9
|
+
|
|
10
|
+
## React Compiler
|
|
11
|
+
|
|
12
|
+
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
|
|
13
|
+
|
|
14
|
+
## Expanding the ESLint configuration
|
|
15
|
+
|
|
16
|
+
If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import js from '@eslint/js'
|
|
2
|
+
import globals from 'globals'
|
|
3
|
+
import reactHooks from 'eslint-plugin-react-hooks'
|
|
4
|
+
import reactRefresh from 'eslint-plugin-react-refresh'
|
|
5
|
+
import { defineConfig, globalIgnores } from 'eslint/config'
|
|
6
|
+
|
|
7
|
+
export default defineConfig([
|
|
8
|
+
globalIgnores(['dist']),
|
|
9
|
+
{
|
|
10
|
+
files: ['**/*.{js,jsx}'],
|
|
11
|
+
extends: [
|
|
12
|
+
js.configs.recommended,
|
|
13
|
+
reactHooks.configs.flat.recommended,
|
|
14
|
+
reactRefresh.configs.vite,
|
|
15
|
+
],
|
|
16
|
+
languageOptions: {
|
|
17
|
+
globals: globals.browser,
|
|
18
|
+
parserOptions: { ecmaFeatures: { jsx: true } },
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
])
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>client</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="root"></div>
|
|
11
|
+
<script type="module" src="/src/main.jsx"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "client",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"lint": "eslint .",
|
|
10
|
+
"preview": "vite preview"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@tailwindcss/vite": "^4.3.0",
|
|
14
|
+
"axios": "^1.16.1",
|
|
15
|
+
"jspdf": "^4.2.1",
|
|
16
|
+
"jspdf-autotable": "^5.0.8",
|
|
17
|
+
"lucide-react": "^1.16.0",
|
|
18
|
+
"react": "^19.2.6",
|
|
19
|
+
"react-dom": "^19.2.6",
|
|
20
|
+
"react-router-dom": "^7.15.1",
|
|
21
|
+
"react-toastify": "^11.1.0",
|
|
22
|
+
"tailwindcss": "^4.3.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@eslint/js": "^10.0.1",
|
|
26
|
+
"@types/react": "^19.2.14",
|
|
27
|
+
"@types/react-dom": "^19.2.3",
|
|
28
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
29
|
+
"eslint": "^10.3.0",
|
|
30
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
31
|
+
"eslint-plugin-react-refresh": "^0.5.2",
|
|
32
|
+
"globals": "^17.6.0",
|
|
33
|
+
"vite": "^8.0.12"
|
|
34
|
+
}
|
|
35
|
+
}
|