create-ishvexa-app 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/index.js +62 -0
- package/package.json +14 -0
- package/templates/epms-app/.env +7 -0
- package/templates/epms-app/README.md +113 -0
- package/templates/epms-app/backend-mongodb/.env +3 -0
- package/templates/epms-app/backend-mongodb/.env.example +3 -0
- package/templates/epms-app/backend-mongodb/config/db.js +29 -0
- package/templates/epms-app/backend-mongodb/controllers/authController.js +93 -0
- package/templates/epms-app/backend-mongodb/controllers/departmentController.js +24 -0
- package/templates/epms-app/backend-mongodb/controllers/employeeController.js +39 -0
- package/templates/epms-app/backend-mongodb/controllers/reportController.js +57 -0
- package/templates/epms-app/backend-mongodb/controllers/salaryController.js +101 -0
- package/templates/epms-app/backend-mongodb/middleware/auth.js +16 -0
- package/templates/epms-app/backend-mongodb/models/Counter.js +13 -0
- package/templates/epms-app/backend-mongodb/models/Department.js +11 -0
- package/templates/epms-app/backend-mongodb/models/Employee.js +18 -0
- package/templates/epms-app/backend-mongodb/models/Salary.js +19 -0
- package/templates/epms-app/backend-mongodb/models/User.js +9 -0
- package/templates/epms-app/backend-mongodb/package-lock.json +1571 -0
- package/templates/epms-app/backend-mongodb/package.json +22 -0
- package/templates/epms-app/backend-mongodb/routes/authRoutes.js +8 -0
- package/templates/epms-app/backend-mongodb/routes/departmentRoutes.js +6 -0
- package/templates/epms-app/backend-mongodb/routes/employeeRoutes.js +6 -0
- package/templates/epms-app/backend-mongodb/routes/reportRoutes.js +5 -0
- package/templates/epms-app/backend-mongodb/routes/salaryRoutes.js +8 -0
- package/templates/epms-app/backend-mongodb/server.js +39 -0
- package/templates/epms-app/backend-mysql/.env +7 -0
- package/templates/epms-app/backend-mysql/.env.example +7 -0
- package/templates/epms-app/backend-mysql/config/db.js +33 -0
- package/templates/epms-app/backend-mysql/controllers/authController.js +98 -0
- package/templates/epms-app/backend-mysql/controllers/departmentController.js +25 -0
- package/templates/epms-app/backend-mysql/controllers/employeeController.js +39 -0
- package/templates/epms-app/backend-mysql/controllers/reportController.js +41 -0
- package/templates/epms-app/backend-mysql/controllers/salaryController.js +93 -0
- package/templates/epms-app/backend-mysql/database/schema.sql +7 -0
- package/templates/epms-app/backend-mysql/middleware/auth.js +16 -0
- package/templates/epms-app/backend-mysql/package-lock.json +1486 -0
- package/templates/epms-app/backend-mysql/package.json +23 -0
- package/templates/epms-app/backend-mysql/routes/authRoutes.js +8 -0
- package/templates/epms-app/backend-mysql/routes/departmentRoutes.js +6 -0
- package/templates/epms-app/backend-mysql/routes/employeeRoutes.js +6 -0
- package/templates/epms-app/backend-mysql/routes/reportRoutes.js +5 -0
- package/templates/epms-app/backend-mysql/routes/salaryRoutes.js +8 -0
- package/templates/epms-app/backend-mysql/server.js +39 -0
- package/templates/epms-app/frontend/README.md +16 -0
- package/templates/epms-app/frontend/eslint.config.js +21 -0
- package/templates/epms-app/frontend/index.html +12 -0
- package/templates/epms-app/frontend/package-lock.json +3033 -0
- package/templates/epms-app/frontend/package.json +23 -0
- package/templates/epms-app/frontend/public/favicon.svg +1 -0
- package/templates/epms-app/frontend/public/icons.svg +24 -0
- package/templates/epms-app/frontend/src/App.css +184 -0
- package/templates/epms-app/frontend/src/App.jsx +31 -0
- package/templates/epms-app/frontend/src/api/authApi.js +7 -0
- package/templates/epms-app/frontend/src/api/client.js +11 -0
- package/templates/epms-app/frontend/src/api/departmentApi.js +5 -0
- package/templates/epms-app/frontend/src/api/employeeApi.js +4 -0
- package/templates/epms-app/frontend/src/api/reportApi.js +4 -0
- package/templates/epms-app/frontend/src/api/salaryApi.js +6 -0
- package/templates/epms-app/frontend/src/api/sparePartsApi.js +3 -0
- package/templates/epms-app/frontend/src/api/usersApi.js +4 -0
- package/templates/epms-app/frontend/src/assets/hero.png +0 -0
- package/templates/epms-app/frontend/src/assets/react.svg +1 -0
- package/templates/epms-app/frontend/src/assets/vite.svg +1 -0
- package/templates/epms-app/frontend/src/components/AppLayout.jsx +49 -0
- package/templates/epms-app/frontend/src/context/AuthContext.jsx +41 -0
- package/templates/epms-app/frontend/src/hooks/.gitkeep +0 -0
- package/templates/epms-app/frontend/src/index.css +2 -0
- package/templates/epms-app/frontend/src/main.jsx +16 -0
- package/templates/epms-app/frontend/src/pages/DepartmentPage.jsx +165 -0
- package/templates/epms-app/frontend/src/pages/DepartmentsPage.jsx +119 -0
- package/templates/epms-app/frontend/src/pages/EmployeePage.jsx +212 -0
- package/templates/epms-app/frontend/src/pages/EmployeesPage.jsx +217 -0
- package/templates/epms-app/frontend/src/pages/ForgotPassword.jsx +103 -0
- package/templates/epms-app/frontend/src/pages/LoginPage.jsx +105 -0
- package/templates/epms-app/frontend/src/pages/RegisterPage.jsx +84 -0
- package/templates/epms-app/frontend/src/pages/ReportsPage.jsx +192 -0
- package/templates/epms-app/frontend/src/pages/ResetPasswordPage.jsx +83 -0
- package/templates/epms-app/frontend/src/pages/SalariesPage.jsx +274 -0
- package/templates/epms-app/frontend/src/pages/SalaryPage.jsx +254 -0
- package/templates/epms-app/frontend/vite.config.js +8 -0
- package/templates/lms-app/.env +9 -0
- package/templates/lms-app/README.md +89 -0
- package/templates/lms-app/backend-mongodb/.env +5 -0
- package/templates/lms-app/backend-mongodb/.env.example +5 -0
- package/templates/lms-app/backend-mongodb/package-lock.json +1583 -0
- package/templates/lms-app/backend-mongodb/package.json +26 -0
- package/templates/lms-app/backend-mongodb/src/config/db.js +10 -0
- package/templates/lms-app/backend-mongodb/src/config/env.js +28 -0
- package/templates/lms-app/backend-mongodb/src/controllers/authController.js +86 -0
- package/templates/lms-app/backend-mongodb/src/controllers/bookController.js +101 -0
- package/templates/lms-app/backend-mongodb/src/controllers/borrowController.js +106 -0
- package/templates/lms-app/backend-mongodb/src/controllers/dashboardController.js +40 -0
- package/templates/lms-app/backend-mongodb/src/controllers/reportController.js +47 -0
- package/templates/lms-app/backend-mongodb/src/controllers/studentController.js +92 -0
- package/templates/lms-app/backend-mongodb/src/ensureSeedData.js +72 -0
- package/templates/lms-app/backend-mongodb/src/middleware/auth.js +29 -0
- package/templates/lms-app/backend-mongodb/src/models/Book.js +14 -0
- package/templates/lms-app/backend-mongodb/src/models/Borrow.js +16 -0
- package/templates/lms-app/backend-mongodb/src/models/Student.js +14 -0
- package/templates/lms-app/backend-mongodb/src/models/User.js +13 -0
- package/templates/lms-app/backend-mongodb/src/routes/authRoutes.js +12 -0
- package/templates/lms-app/backend-mongodb/src/routes/bookRoutes.js +13 -0
- package/templates/lms-app/backend-mongodb/src/routes/borrowRoutes.js +11 -0
- package/templates/lms-app/backend-mongodb/src/routes/dashboardRoutes.js +9 -0
- package/templates/lms-app/backend-mongodb/src/routes/reportRoutes.js +12 -0
- package/templates/lms-app/backend-mongodb/src/routes/studentRoutes.js +13 -0
- package/templates/lms-app/backend-mongodb/src/seed.js +16 -0
- package/templates/lms-app/backend-mongodb/src/server.js +66 -0
- package/templates/lms-app/backend-mysql/.env +9 -0
- package/templates/lms-app/backend-mysql/.env.example +9 -0
- package/templates/lms-app/backend-mysql/database/schema.sql +45 -0
- package/templates/lms-app/backend-mysql/package-lock.json +1462 -0
- package/templates/lms-app/backend-mysql/package.json +23 -0
- package/templates/lms-app/backend-mysql/src/config/db.js +33 -0
- package/templates/lms-app/backend-mysql/src/config/env.js +21 -0
- package/templates/lms-app/backend-mysql/src/controllers/authController.js +87 -0
- package/templates/lms-app/backend-mysql/src/controllers/bookController.js +106 -0
- package/templates/lms-app/backend-mysql/src/controllers/borrowController.js +113 -0
- package/templates/lms-app/backend-mysql/src/controllers/dashboardController.js +33 -0
- package/templates/lms-app/backend-mysql/src/controllers/reportController.js +40 -0
- package/templates/lms-app/backend-mysql/src/controllers/studentController.js +95 -0
- package/templates/lms-app/backend-mysql/src/ensureSeedData.js +54 -0
- package/templates/lms-app/backend-mysql/src/middleware/auth.js +28 -0
- package/templates/lms-app/backend-mysql/src/routes/authRoutes.js +12 -0
- package/templates/lms-app/backend-mysql/src/routes/bookRoutes.js +13 -0
- package/templates/lms-app/backend-mysql/src/routes/borrowRoutes.js +11 -0
- package/templates/lms-app/backend-mysql/src/routes/dashboardRoutes.js +9 -0
- package/templates/lms-app/backend-mysql/src/routes/reportRoutes.js +12 -0
- package/templates/lms-app/backend-mysql/src/routes/studentRoutes.js +13 -0
- package/templates/lms-app/backend-mysql/src/server.js +69 -0
- package/templates/lms-app/backend-mysql/src/utils/mappers.js +73 -0
- package/templates/lms-app/frontend/.env.example +5 -0
- package/templates/lms-app/frontend/index.html +13 -0
- package/templates/lms-app/frontend/package-lock.json +1592 -0
- package/templates/lms-app/frontend/package.json +23 -0
- package/templates/lms-app/frontend/public/favicon.svg +4 -0
- package/templates/lms-app/frontend/src/App.jsx +107 -0
- package/templates/lms-app/frontend/src/api/authApi.js +5 -0
- package/templates/lms-app/frontend/src/api/booksApi.js +6 -0
- package/templates/lms-app/frontend/src/api/borrowsApi.js +5 -0
- package/templates/lms-app/frontend/src/api/client.js +8 -0
- package/templates/lms-app/frontend/src/api/dashboardApi.js +3 -0
- package/templates/lms-app/frontend/src/api/reportsApi.js +6 -0
- package/templates/lms-app/frontend/src/api/studentsApi.js +6 -0
- package/templates/lms-app/frontend/src/components/AppLayout.jsx +63 -0
- package/templates/lms-app/frontend/src/index.css +34 -0
- package/templates/lms-app/frontend/src/main.jsx +13 -0
- package/templates/lms-app/frontend/src/pages/BooksPage.jsx +206 -0
- package/templates/lms-app/frontend/src/pages/BorrowPage.jsx +134 -0
- package/templates/lms-app/frontend/src/pages/DashboardPage.jsx +42 -0
- package/templates/lms-app/frontend/src/pages/ForgotPassword.jsx +112 -0
- package/templates/lms-app/frontend/src/pages/LoginPage.jsx +71 -0
- package/templates/lms-app/frontend/src/pages/ReportsPage.jsx +176 -0
- package/templates/lms-app/frontend/src/pages/ReturnPage.jsx +75 -0
- package/templates/lms-app/frontend/src/pages/SearchPage.jsx +156 -0
- package/templates/lms-app/frontend/src/pages/StudentsPage.jsx +204 -0
- package/templates/lms-app/frontend/vite.config.js +26 -0
- package/templates/scms-app/.env +7 -0
- package/templates/scms-app/README.md +80 -0
- package/templates/scms-app/backend-mongodb/.env +3 -0
- package/templates/scms-app/backend-mongodb/.env.example +3 -0
- package/templates/scms-app/backend-mongodb/config/db.js +29 -0
- package/templates/scms-app/backend-mongodb/controllers/authController.js +93 -0
- package/templates/scms-app/backend-mongodb/controllers/deliveryController.js +65 -0
- package/templates/scms-app/backend-mongodb/controllers/reportController.js +51 -0
- package/templates/scms-app/backend-mongodb/controllers/shipmentController.js +65 -0
- package/templates/scms-app/backend-mongodb/controllers/supplierController.js +27 -0
- package/templates/scms-app/backend-mongodb/middleware/auth.js +16 -0
- package/templates/scms-app/backend-mongodb/models/Delivery.js +14 -0
- package/templates/scms-app/backend-mongodb/models/Shipment.js +14 -0
- package/templates/scms-app/backend-mongodb/models/Supplier.js +14 -0
- package/templates/scms-app/backend-mongodb/models/User.js +9 -0
- package/templates/scms-app/backend-mongodb/package-lock.json +1571 -0
- package/templates/scms-app/backend-mongodb/package.json +22 -0
- package/templates/scms-app/backend-mongodb/routes/authRoutes.js +8 -0
- package/templates/scms-app/backend-mongodb/routes/deliveryRoutes.js +8 -0
- package/templates/scms-app/backend-mongodb/routes/reportRoutes.js +5 -0
- package/templates/scms-app/backend-mongodb/routes/shipmentRoutes.js +8 -0
- package/templates/scms-app/backend-mongodb/routes/supplierRoutes.js +6 -0
- package/templates/scms-app/backend-mongodb/server.js +39 -0
- package/templates/scms-app/backend-mysql/.env +7 -0
- package/templates/scms-app/backend-mysql/.env.example +7 -0
- package/templates/scms-app/backend-mysql/config/db.js +33 -0
- package/templates/scms-app/backend-mysql/controllers/authController.js +98 -0
- package/templates/scms-app/backend-mysql/controllers/deliveryController.js +62 -0
- package/templates/scms-app/backend-mysql/controllers/reportController.js +39 -0
- package/templates/scms-app/backend-mysql/controllers/shipmentController.js +62 -0
- package/templates/scms-app/backend-mysql/controllers/supplierController.js +28 -0
- package/templates/scms-app/backend-mysql/database/schema.sql +7 -0
- package/templates/scms-app/backend-mysql/middleware/auth.js +16 -0
- package/templates/scms-app/backend-mysql/package-lock.json +1486 -0
- package/templates/scms-app/backend-mysql/package.json +23 -0
- package/templates/scms-app/backend-mysql/routes/authRoutes.js +8 -0
- package/templates/scms-app/backend-mysql/routes/deliveryRoutes.js +8 -0
- package/templates/scms-app/backend-mysql/routes/reportRoutes.js +5 -0
- package/templates/scms-app/backend-mysql/routes/shipmentRoutes.js +8 -0
- package/templates/scms-app/backend-mysql/routes/supplierRoutes.js +6 -0
- package/templates/scms-app/backend-mysql/server.js +39 -0
- package/templates/scms-app/frontend/index.html +12 -0
- package/templates/scms-app/frontend/package-lock.json +1634 -0
- package/templates/scms-app/frontend/package.json +23 -0
- package/templates/scms-app/frontend/src/App.jsx +31 -0
- package/templates/scms-app/frontend/src/api/client.js +11 -0
- package/templates/scms-app/frontend/src/components/AppLayout.jsx +49 -0
- package/templates/scms-app/frontend/src/context/AuthContext.jsx +41 -0
- package/templates/scms-app/frontend/src/hooks/.gitkeep +0 -0
- package/templates/scms-app/frontend/src/index.css +2 -0
- package/templates/scms-app/frontend/src/main.jsx +16 -0
- package/templates/scms-app/frontend/src/pages/DeliveriesPage.jsx +265 -0
- package/templates/scms-app/frontend/src/pages/ForgotPassword.jsx +103 -0
- package/templates/scms-app/frontend/src/pages/LoginPage.jsx +105 -0
- package/templates/scms-app/frontend/src/pages/ReportsPage.jsx +192 -0
- package/templates/scms-app/frontend/src/pages/ShipmentsPage.jsx +259 -0
- package/templates/scms-app/frontend/src/pages/SuppliersPage.jsx +168 -0
- package/templates/scms-app/frontend/vite.config.js +8 -0
- package/templates/sfms-app/.env +7 -0
- package/templates/sfms-app/README.md +72 -0
- package/templates/sfms-app/backend-mongodb/.env +3 -0
- package/templates/sfms-app/backend-mongodb/.env.example +3 -0
- package/templates/sfms-app/backend-mongodb/package-lock.json +1580 -0
- package/templates/sfms-app/backend-mongodb/package.json +23 -0
- package/templates/sfms-app/backend-mongodb/src/config/database.js +7 -0
- package/templates/sfms-app/backend-mongodb/src/config/env.js +35 -0
- package/templates/sfms-app/backend-mongodb/src/middleware/authMiddleware.js +32 -0
- package/templates/sfms-app/backend-mongodb/src/models/Payment.js +12 -0
- package/templates/sfms-app/backend-mongodb/src/models/Student.js +12 -0
- package/templates/sfms-app/backend-mongodb/src/models/User.js +14 -0
- package/templates/sfms-app/backend-mongodb/src/routes/authRoutes.js +140 -0
- package/templates/sfms-app/backend-mongodb/src/routes/paymentRoutes.js +117 -0
- package/templates/sfms-app/backend-mongodb/src/routes/reportRoutes.js +59 -0
- package/templates/sfms-app/backend-mongodb/src/routes/studentRoutes.js +79 -0
- package/templates/sfms-app/backend-mongodb/src/server.js +34 -0
- package/templates/sfms-app/backend-mysql/.env +7 -0
- package/templates/sfms-app/backend-mysql/.env.example +7 -0
- package/templates/sfms-app/backend-mysql/database/schema.sql +29 -0
- package/templates/sfms-app/backend-mysql/package-lock.json +1467 -0
- package/templates/sfms-app/backend-mysql/package.json +24 -0
- package/templates/sfms-app/backend-mysql/src/config/.gitkeep +0 -0
- package/templates/sfms-app/backend-mysql/src/config/db.js +31 -0
- package/templates/sfms-app/backend-mysql/src/config/env.js +20 -0
- package/templates/sfms-app/backend-mysql/src/middleware/.gitkeep +0 -0
- package/templates/sfms-app/backend-mysql/src/middleware/authMiddleware.js +26 -0
- package/templates/sfms-app/backend-mysql/src/models/.gitkeep +0 -0
- package/templates/sfms-app/backend-mysql/src/routes/.gitkeep +0 -0
- package/templates/sfms-app/backend-mysql/src/routes/authRoutes.js +131 -0
- package/templates/sfms-app/backend-mysql/src/routes/paymentRoutes.js +92 -0
- package/templates/sfms-app/backend-mysql/src/routes/reportRoutes.js +41 -0
- package/templates/sfms-app/backend-mysql/src/routes/studentRoutes.js +75 -0
- package/templates/sfms-app/backend-mysql/src/server.js +39 -0
- package/templates/sfms-app/backend-mysql/src/utils/mappers.js +43 -0
- package/templates/sfms-app/frontend/.env.example +9 -0
- package/templates/sfms-app/frontend/index.html +19 -0
- package/templates/sfms-app/frontend/package-lock.json +2667 -0
- package/templates/sfms-app/frontend/package.json +23 -0
- package/templates/sfms-app/frontend/postcss.config.js +6 -0
- package/templates/sfms-app/frontend/public/favicon.svg +4 -0
- package/templates/sfms-app/frontend/src/App.jsx +38 -0
- package/templates/sfms-app/frontend/src/api/apiClient.js +54 -0
- package/templates/sfms-app/frontend/src/components/AppLayout.jsx +61 -0
- package/templates/sfms-app/frontend/src/context/AuthContext.jsx +87 -0
- package/templates/sfms-app/frontend/src/index.css +7 -0
- package/templates/sfms-app/frontend/src/main.jsx +16 -0
- package/templates/sfms-app/frontend/src/pages/DashboardPage.jsx +78 -0
- package/templates/sfms-app/frontend/src/pages/ForgotPassword.jsx +114 -0
- package/templates/sfms-app/frontend/src/pages/LoginPage.jsx +141 -0
- package/templates/sfms-app/frontend/src/pages/PaymentsPage.jsx +309 -0
- package/templates/sfms-app/frontend/src/pages/ReportsPage.jsx +123 -0
- package/templates/sfms-app/frontend/src/pages/StudentsPage.jsx +281 -0
- package/templates/sfms-app/frontend/tailwind.config.js +21 -0
- package/templates/sfms-app/frontend/vite.config.js +61 -0
- package/templates/sims-app/README.md +138 -0
- package/templates/sims-app/backend/.env +4 -0
- package/templates/sims-app/backend/.env.example +4 -0
- package/templates/sims-app/backend/package.json +22 -0
- package/templates/sims-app/backend/src/config/db.js +9 -0
- package/templates/sims-app/backend/src/controllers/authController.js +115 -0
- package/templates/sims-app/backend/src/controllers/simsReportController.js +94 -0
- package/templates/sims-app/backend/src/controllers/sparePartController.js +41 -0
- package/templates/sims-app/backend/src/controllers/stockInController.js +45 -0
- package/templates/sims-app/backend/src/controllers/stockOutController.js +123 -0
- package/templates/sims-app/backend/src/middleware/auth.js +8 -0
- package/templates/sims-app/backend/src/models/SparePart.js +17 -0
- package/templates/sims-app/backend/src/models/StockIn.js +16 -0
- package/templates/sims-app/backend/src/models/StockOut.js +18 -0
- package/templates/sims-app/backend/src/models/User.js +12 -0
- package/templates/sims-app/backend/src/routes/authRoutes.js +12 -0
- package/templates/sims-app/backend/src/routes/simsReportRoutes.js +8 -0
- package/templates/sims-app/backend/src/routes/sparePartRoutes.js +8 -0
- package/templates/sims-app/backend/src/routes/stockInRoutes.js +8 -0
- package/templates/sims-app/backend/src/routes/stockOutRoutes.js +10 -0
- package/templates/sims-app/backend/src/server.js +62 -0
- package/templates/sims-app/backend/src/utils/passwordPolicy.js +10 -0
- package/templates/sims-app/backend/src/utils/sparePartHelpers.js +5 -0
- package/templates/sims-app/frontend/index.html +13 -0
- package/templates/sims-app/frontend/package.json +31 -0
- package/templates/sims-app/frontend/src/App.jsx +110 -0
- package/templates/sims-app/frontend/src/api/authApi.js +7 -0
- package/templates/sims-app/frontend/src/api/client.js +8 -0
- package/templates/sims-app/frontend/src/api/simsReportApi.js +5 -0
- package/templates/sims-app/frontend/src/api/sparePartsApi.js +4 -0
- package/templates/sims-app/frontend/src/api/stockInApi.js +4 -0
- package/templates/sims-app/frontend/src/api/stockOutApi.js +6 -0
- package/templates/sims-app/frontend/src/api/usersApi.js +3 -0
- package/templates/sims-app/frontend/src/components/AppLayout.jsx +47 -0
- package/templates/sims-app/frontend/src/index.css +7 -0
- package/templates/sims-app/frontend/src/main.jsx +13 -0
- package/templates/sims-app/frontend/src/pages/ForgotPassword.jsx +111 -0
- package/templates/sims-app/frontend/src/pages/LoginPage.jsx +71 -0
- package/templates/sims-app/frontend/src/pages/RegisterPage.jsx +99 -0
- package/templates/sims-app/frontend/src/pages/ReportsPage.jsx +120 -0
- package/templates/sims-app/frontend/src/pages/SparePartPage.jsx +148 -0
- package/templates/sims-app/frontend/src/pages/StockInPage.jsx +122 -0
- package/templates/sims-app/frontend/src/pages/StockOutPage.jsx +252 -0
- package/templates/sims-app/frontend/src/utils/passwordPolicy.js +8 -0
- package/templates/sims-app/frontend/vite.config.js +8 -0
- package/templates/smartshop-app/README.md +61 -0
- package/templates/smartshop-app/backend/.env +7 -0
- package/templates/smartshop-app/backend/.env.example +7 -0
- package/templates/smartshop-app/backend/database/schema.sql +46 -0
- package/templates/smartshop-app/backend/package-lock.json +1487 -0
- package/templates/smartshop-app/backend/package.json +26 -0
- package/templates/smartshop-app/backend/src/app.js +57 -0
- package/templates/smartshop-app/backend/src/config/db.js +52 -0
- package/templates/smartshop-app/backend/src/controllers/authController.js +98 -0
- package/templates/smartshop-app/backend/src/controllers/customerController.js +26 -0
- package/templates/smartshop-app/backend/src/controllers/productController.js +21 -0
- package/templates/smartshop-app/backend/src/controllers/reportController.js +29 -0
- package/templates/smartshop-app/backend/src/controllers/saleController.js +11 -0
- package/templates/smartshop-app/backend/src/middleware/authMiddleware.js +22 -0
- package/templates/smartshop-app/backend/src/models/authModel.js +24 -0
- package/templates/smartshop-app/backend/src/models/customerModel.js +43 -0
- package/templates/smartshop-app/backend/src/models/productModel.js +37 -0
- package/templates/smartshop-app/backend/src/models/reportModel.js +56 -0
- package/templates/smartshop-app/backend/src/models/saleModel.js +54 -0
- package/templates/smartshop-app/backend/src/routes/authRoutes.js +10 -0
- package/templates/smartshop-app/backend/src/routes/customerRoutes.js +16 -0
- package/templates/smartshop-app/backend/src/routes/productRoutes.js +16 -0
- package/templates/smartshop-app/backend/src/routes/reportRoutes.js +18 -0
- package/templates/smartshop-app/backend/src/routes/saleRoutes.js +9 -0
- package/templates/smartshop-app/backend/src/server.js +19 -0
- package/templates/smartshop-app/frontend/README.md +18 -0
- package/templates/smartshop-app/frontend/eslint.config.js +21 -0
- package/templates/smartshop-app/frontend/index.html +13 -0
- package/templates/smartshop-app/frontend/package-lock.json +3415 -0
- package/templates/smartshop-app/frontend/package.json +34 -0
- package/templates/smartshop-app/frontend/public/favicon.svg +1 -0
- package/templates/smartshop-app/frontend/public/icons.svg +24 -0
- package/templates/smartshop-app/frontend/src/App.css +184 -0
- package/templates/smartshop-app/frontend/src/App.jsx +41 -0
- package/templates/smartshop-app/frontend/src/assets/hero.png +0 -0
- package/templates/smartshop-app/frontend/src/assets/react.svg +1 -0
- package/templates/smartshop-app/frontend/src/assets/vite.svg +1 -0
- package/templates/smartshop-app/frontend/src/components/AppLayout.jsx +71 -0
- package/templates/smartshop-app/frontend/src/components/FormCard.jsx +12 -0
- package/templates/smartshop-app/frontend/src/components/StatCard.jsx +10 -0
- package/templates/smartshop-app/frontend/src/index.css +28 -0
- package/templates/smartshop-app/frontend/src/main.jsx +13 -0
- package/templates/smartshop-app/frontend/src/pages/CustomersPage.jsx +175 -0
- package/templates/smartshop-app/frontend/src/pages/DashboardPage.jsx +30 -0
- package/templates/smartshop-app/frontend/src/pages/ForgotPassword.jsx +102 -0
- package/templates/smartshop-app/frontend/src/pages/LoginPage.jsx +142 -0
- package/templates/smartshop-app/frontend/src/pages/ProductsPage.jsx +165 -0
- package/templates/smartshop-app/frontend/src/pages/ReportsPage.jsx +204 -0
- package/templates/smartshop-app/frontend/src/pages/SalesPage.jsx +153 -0
- package/templates/smartshop-app/frontend/src/services/api.js +15 -0
- package/templates/smartshop-app/frontend/vite.config.js +13 -0
- package/templates/srms-app/.env +7 -0
- package/templates/srms-app/README.md +82 -0
- package/templates/srms-app/backend-mongodb/.env +3 -0
- package/templates/srms-app/backend-mongodb/.env.example +3 -0
- package/templates/srms-app/backend-mongodb/config/db.js +29 -0
- package/templates/srms-app/backend-mongodb/controllers/authController.js +93 -0
- package/templates/srms-app/backend-mongodb/controllers/customerController.js +27 -0
- package/templates/srms-app/backend-mongodb/controllers/productController.js +26 -0
- package/templates/srms-app/backend-mongodb/controllers/reportController.js +44 -0
- package/templates/srms-app/backend-mongodb/controllers/saleController.js +72 -0
- package/templates/srms-app/backend-mongodb/middleware/auth.js +16 -0
- package/templates/srms-app/backend-mongodb/models/Customer.js +14 -0
- package/templates/srms-app/backend-mongodb/models/Product.js +13 -0
- package/templates/srms-app/backend-mongodb/models/Sale.js +15 -0
- package/templates/srms-app/backend-mongodb/models/User.js +9 -0
- package/templates/srms-app/backend-mongodb/package-lock.json +1571 -0
- package/templates/srms-app/backend-mongodb/package.json +22 -0
- package/templates/srms-app/backend-mongodb/routes/authRoutes.js +8 -0
- package/templates/srms-app/backend-mongodb/routes/customerRoutes.js +6 -0
- package/templates/srms-app/backend-mongodb/routes/productRoutes.js +6 -0
- package/templates/srms-app/backend-mongodb/routes/reportRoutes.js +5 -0
- package/templates/srms-app/backend-mongodb/routes/saleRoutes.js +8 -0
- package/templates/srms-app/backend-mongodb/server.js +39 -0
- package/templates/srms-app/backend-mysql/.env +7 -0
- package/templates/srms-app/backend-mysql/.env.example +7 -0
- package/templates/srms-app/backend-mysql/config/db.js +33 -0
- package/templates/srms-app/backend-mysql/controllers/authController.js +98 -0
- package/templates/srms-app/backend-mysql/controllers/customerController.js +28 -0
- package/templates/srms-app/backend-mysql/controllers/productController.js +27 -0
- package/templates/srms-app/backend-mysql/controllers/reportController.js +29 -0
- package/templates/srms-app/backend-mysql/controllers/saleController.js +68 -0
- package/templates/srms-app/backend-mysql/database/schema.sql +7 -0
- package/templates/srms-app/backend-mysql/middleware/auth.js +16 -0
- package/templates/srms-app/backend-mysql/package-lock.json +1486 -0
- package/templates/srms-app/backend-mysql/package.json +23 -0
- package/templates/srms-app/backend-mysql/routes/authRoutes.js +8 -0
- package/templates/srms-app/backend-mysql/routes/customerRoutes.js +6 -0
- package/templates/srms-app/backend-mysql/routes/productRoutes.js +6 -0
- package/templates/srms-app/backend-mysql/routes/reportRoutes.js +5 -0
- package/templates/srms-app/backend-mysql/routes/saleRoutes.js +8 -0
- package/templates/srms-app/backend-mysql/server.js +39 -0
- package/templates/srms-app/frontend/index.html +12 -0
- package/templates/srms-app/frontend/package-lock.json +1634 -0
- package/templates/srms-app/frontend/package.json +23 -0
- package/templates/srms-app/frontend/src/App.jsx +31 -0
- package/templates/srms-app/frontend/src/api/client.js +11 -0
- package/templates/srms-app/frontend/src/components/AppLayout.jsx +40 -0
- package/templates/srms-app/frontend/src/context/AuthContext.jsx +41 -0
- package/templates/srms-app/frontend/src/hooks/.gitkeep +0 -0
- package/templates/srms-app/frontend/src/index.css +2 -0
- package/templates/srms-app/frontend/src/main.jsx +16 -0
- package/templates/srms-app/frontend/src/pages/CustomersPage.jsx +160 -0
- package/templates/srms-app/frontend/src/pages/ForgotPassword.jsx +103 -0
- package/templates/srms-app/frontend/src/pages/LoginPage.jsx +105 -0
- package/templates/srms-app/frontend/src/pages/ProductsPage.jsx +158 -0
- package/templates/srms-app/frontend/src/pages/ReportsPage.jsx +192 -0
- package/templates/srms-app/frontend/src/pages/SalesPage.jsx +310 -0
- package/templates/srms-app/frontend/vite.config.js +8 -0
- package/templates/stockhub-sms-app/.env +7 -0
- package/templates/stockhub-sms-app/README.md +82 -0
- package/templates/stockhub-sms-app/backend-mongodb/.env +3 -0
- package/templates/stockhub-sms-app/backend-mongodb/.env.example +3 -0
- package/templates/stockhub-sms-app/backend-mongodb/config/db.js +29 -0
- package/templates/stockhub-sms-app/backend-mongodb/controllers/authController.js +93 -0
- package/templates/stockhub-sms-app/backend-mongodb/controllers/productController.js +29 -0
- package/templates/stockhub-sms-app/backend-mongodb/controllers/reportController.js +53 -0
- package/templates/stockhub-sms-app/backend-mongodb/controllers/transactionController.js +74 -0
- package/templates/stockhub-sms-app/backend-mongodb/controllers/warehouseController.js +25 -0
- package/templates/stockhub-sms-app/backend-mongodb/middleware/auth.js +16 -0
- package/templates/stockhub-sms-app/backend-mongodb/models/Counter.js +13 -0
- package/templates/stockhub-sms-app/backend-mongodb/models/Product.js +16 -0
- package/templates/stockhub-sms-app/backend-mongodb/models/StockTransaction.js +19 -0
- package/templates/stockhub-sms-app/backend-mongodb/models/User.js +9 -0
- package/templates/stockhub-sms-app/backend-mongodb/models/Warehouse.js +12 -0
- package/templates/stockhub-sms-app/backend-mongodb/package-lock.json +1571 -0
- package/templates/stockhub-sms-app/backend-mongodb/package.json +22 -0
- package/templates/stockhub-sms-app/backend-mongodb/routes/authRoutes.js +8 -0
- package/templates/stockhub-sms-app/backend-mongodb/routes/productRoutes.js +6 -0
- package/templates/stockhub-sms-app/backend-mongodb/routes/reportRoutes.js +5 -0
- package/templates/stockhub-sms-app/backend-mongodb/routes/transactionRoutes.js +8 -0
- package/templates/stockhub-sms-app/backend-mongodb/routes/warehouseRoutes.js +6 -0
- package/templates/stockhub-sms-app/backend-mongodb/server.js +39 -0
- package/templates/stockhub-sms-app/backend-mysql/.env +7 -0
- package/templates/stockhub-sms-app/backend-mysql/.env.example +7 -0
- package/templates/stockhub-sms-app/backend-mysql/config/db.js +33 -0
- package/templates/stockhub-sms-app/backend-mysql/controllers/authController.js +98 -0
- package/templates/stockhub-sms-app/backend-mysql/controllers/productController.js +30 -0
- package/templates/stockhub-sms-app/backend-mysql/controllers/reportController.js +53 -0
- package/templates/stockhub-sms-app/backend-mysql/controllers/transactionController.js +70 -0
- package/templates/stockhub-sms-app/backend-mysql/controllers/warehouseController.js +26 -0
- package/templates/stockhub-sms-app/backend-mysql/database/schema.sql +40 -0
- package/templates/stockhub-sms-app/backend-mysql/middleware/auth.js +16 -0
- package/templates/stockhub-sms-app/backend-mysql/package-lock.json +1486 -0
- package/templates/stockhub-sms-app/backend-mysql/package.json +23 -0
- package/templates/stockhub-sms-app/backend-mysql/routes/authRoutes.js +8 -0
- package/templates/stockhub-sms-app/backend-mysql/routes/productRoutes.js +6 -0
- package/templates/stockhub-sms-app/backend-mysql/routes/reportRoutes.js +5 -0
- package/templates/stockhub-sms-app/backend-mysql/routes/transactionRoutes.js +8 -0
- package/templates/stockhub-sms-app/backend-mysql/routes/warehouseRoutes.js +6 -0
- package/templates/stockhub-sms-app/backend-mysql/server.js +39 -0
- package/templates/stockhub-sms-app/frontend/index.html +12 -0
- package/templates/stockhub-sms-app/frontend/package-lock.json +1634 -0
- package/templates/stockhub-sms-app/frontend/package.json +23 -0
- package/templates/stockhub-sms-app/frontend/src/App.jsx +31 -0
- package/templates/stockhub-sms-app/frontend/src/api/client.js +11 -0
- package/templates/stockhub-sms-app/frontend/src/components/AppLayout.jsx +40 -0
- package/templates/stockhub-sms-app/frontend/src/context/AuthContext.jsx +41 -0
- package/templates/stockhub-sms-app/frontend/src/hooks/.gitkeep +0 -0
- package/templates/stockhub-sms-app/frontend/src/index.css +13 -0
- package/templates/stockhub-sms-app/frontend/src/main.jsx +16 -0
- package/templates/stockhub-sms-app/frontend/src/pages/ForgotPassword.jsx +103 -0
- package/templates/stockhub-sms-app/frontend/src/pages/LoginPage.jsx +105 -0
- package/templates/stockhub-sms-app/frontend/src/pages/ProductsPage.jsx +132 -0
- package/templates/stockhub-sms-app/frontend/src/pages/ReportsPage.jsx +177 -0
- package/templates/stockhub-sms-app/frontend/src/pages/TransactionsPage.jsx +270 -0
- package/templates/stockhub-sms-app/frontend/src/pages/WarehousesPage.jsx +116 -0
- package/templates/stockhub-sms-app/frontend/vite.config.js +8 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "backend",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Sales management backend",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/server.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"db:init": "bash -c 'set -a && source .env && set +a && if [ -n \"$DB_PASSWORD\" ]; then mysql -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$DB_USER\" -p\"$DB_PASSWORD\" < database/schema.sql; else mysql -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$DB_USER\" < database/schema.sql; fi'",
|
|
9
|
+
"db:reset": "bash -c 'set -a && source .env && set +a && if [ -n \"$DB_PASSWORD\" ]; then mysql -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$DB_USER\" -p\"$DB_PASSWORD\" -e \"DROP DATABASE IF EXISTS $DB_NAME;\" && mysql -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$DB_USER\" -p\"$DB_PASSWORD\" < database/schema.sql; else mysql -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$DB_USER\" -e \"DROP DATABASE IF EXISTS $DB_NAME;\" && mysql -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$DB_USER\" < database/schema.sql; fi'",
|
|
10
|
+
"dev": "nodemon src/server.js",
|
|
11
|
+
"start": "node src/server.js"
|
|
12
|
+
},
|
|
13
|
+
"author": "",
|
|
14
|
+
"license": "ISC",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"bcryptjs": "^3.0.3",
|
|
17
|
+
"cors": "^2.8.6",
|
|
18
|
+
"dotenv": "^17.4.2",
|
|
19
|
+
"express": "^5.2.1",
|
|
20
|
+
"jsonwebtoken": "^9.0.3",
|
|
21
|
+
"mysql2": "^3.22.4"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"nodemon": "^3.1.14"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import cors from "cors";
|
|
3
|
+
import { query } from "./config/db.js";
|
|
4
|
+
|
|
5
|
+
import authRoutes from "./routes/authRoutes.js";
|
|
6
|
+
import productRoutes from "./routes/productRoutes.js";
|
|
7
|
+
import customerRoutes from "./routes/customerRoutes.js";
|
|
8
|
+
import saleRoutes from "./routes/saleRoutes.js";
|
|
9
|
+
import reportRoutes from "./routes/reportRoutes.js";
|
|
10
|
+
import authMiddleware from "./middleware/authMiddleware.js";
|
|
11
|
+
|
|
12
|
+
const app = express();
|
|
13
|
+
|
|
14
|
+
app.use(cors());
|
|
15
|
+
app.use(express.json());
|
|
16
|
+
|
|
17
|
+
app.get("/api/health", (_req, res) => {
|
|
18
|
+
res.json({ status: "ok", service: "SMS API" });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
app.get("/api/health/database", async (_req, res) => {
|
|
22
|
+
try {
|
|
23
|
+
await query("SELECT 1");
|
|
24
|
+
res.json({
|
|
25
|
+
status: "ok",
|
|
26
|
+
database: "running",
|
|
27
|
+
message: "Database is running.",
|
|
28
|
+
});
|
|
29
|
+
} catch (error) {
|
|
30
|
+
// eslint-disable-next-line no-console
|
|
31
|
+
console.error("[DB HEALTH CHECK] Database check failed.");
|
|
32
|
+
// eslint-disable-next-line no-console
|
|
33
|
+
console.error(`[DB HEALTH CHECK] Code: ${error?.code || "UNKNOWN"}`);
|
|
34
|
+
// eslint-disable-next-line no-console
|
|
35
|
+
console.error(`[DB HEALTH CHECK] Message: ${error?.message || "No message provided."}`);
|
|
36
|
+
res.status(503).json({
|
|
37
|
+
status: "error",
|
|
38
|
+
database: "not running",
|
|
39
|
+
message: "Database is not running or connection failed.",
|
|
40
|
+
errorCode: error?.code || "UNKNOWN",
|
|
41
|
+
errorReason: error?.message || "No reason provided.",
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
app.use("/api/auth", authRoutes);
|
|
47
|
+
app.use("/api/products", authMiddleware, productRoutes);
|
|
48
|
+
app.use("/api/customers", authMiddleware, customerRoutes);
|
|
49
|
+
app.use("/api/sales", authMiddleware, saleRoutes);
|
|
50
|
+
app.use("/api/reports", authMiddleware, reportRoutes);
|
|
51
|
+
|
|
52
|
+
app.use((error, _req, res, _next) => {
|
|
53
|
+
const message = error?.message || "Server error";
|
|
54
|
+
res.status(500).json({ message });
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
export default app;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import mysql from "mysql2/promise";
|
|
2
|
+
import dotenv from "dotenv";
|
|
3
|
+
|
|
4
|
+
dotenv.config();
|
|
5
|
+
|
|
6
|
+
const pool = mysql.createPool({
|
|
7
|
+
host: process.env.DB_HOST || "localhost",
|
|
8
|
+
user: process.env.DB_USER || "student",
|
|
9
|
+
password: process.env.DB_PASSWORD || "",
|
|
10
|
+
database: process.env.DB_NAME || "smartshop_db",
|
|
11
|
+
port: Number(process.env.DB_PORT || 3306),
|
|
12
|
+
waitForConnections: true,
|
|
13
|
+
connectionLimit: 10,
|
|
14
|
+
queueLimit: 0,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const getFailureReason = (error) => {
|
|
18
|
+
const reasons = {
|
|
19
|
+
ECONNREFUSED: "MySQL server is not started or host/port is wrong.",
|
|
20
|
+
ER_ACCESS_DENIED_ERROR: "Invalid database username or password.",
|
|
21
|
+
ER_BAD_DB_ERROR: "Database name does not exist.",
|
|
22
|
+
ETIMEDOUT: "Database connection timed out.",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
return reasons[error?.code] || "Unknown database connection issue.";
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const query = async (sql, params = []) => {
|
|
29
|
+
const [rows] = await pool.execute(sql, params);
|
|
30
|
+
return rows;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const checkDatabaseConnection = async () => {
|
|
34
|
+
try {
|
|
35
|
+
await query("SELECT 1");
|
|
36
|
+
|
|
37
|
+
console.log("[DB] Connection successful. Database is running.");
|
|
38
|
+
return { ok: true };
|
|
39
|
+
} catch (error) {
|
|
40
|
+
|
|
41
|
+
console.error("[DB] CONNECTION FAILED");
|
|
42
|
+
|
|
43
|
+
console.error(`[DB] Error code: ${error?.code || "UNKNOWN"}`);
|
|
44
|
+
|
|
45
|
+
console.error(`[DB] Error message: ${error?.message || "No message provided."}`);
|
|
46
|
+
|
|
47
|
+
console.error(`[DB] Reason: ${getFailureReason(error)}`);
|
|
48
|
+
return { ok: false, error, reason: getFailureReason(error) };
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default pool;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import bcrypt from "bcryptjs";
|
|
2
|
+
import jwt from "jsonwebtoken";
|
|
3
|
+
import { createUser, findUserByUsername, findUserByEmail, updatePasswordByEmail } from "../models/authModel.js";
|
|
4
|
+
|
|
5
|
+
const createAccessToken = (payload) =>
|
|
6
|
+
jwt.sign(payload, process.env.JWT_SECRET || "smartshop_student_project_secret", {
|
|
7
|
+
expiresIn: "8h",
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const normalizeEmail = (email) => String(email || "").trim().toLowerCase();
|
|
11
|
+
|
|
12
|
+
export const register = async (req, res) => {
|
|
13
|
+
const { username, email, password } = req.body;
|
|
14
|
+
if (!username || !email || !password) {
|
|
15
|
+
return res.status(400).json({ message: "Username, email and password are required." });
|
|
16
|
+
}
|
|
17
|
+
const emailNorm = normalizeEmail(email);
|
|
18
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailNorm)) {
|
|
19
|
+
return res.status(400).json({ message: "Enter a valid email address." });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const existing = await findUserByUsername(username.trim());
|
|
23
|
+
if (existing.length) {
|
|
24
|
+
return res.status(409).json({ message: "Username already exists." });
|
|
25
|
+
}
|
|
26
|
+
const existingEmail = await findUserByEmail(emailNorm);
|
|
27
|
+
if (existingEmail.length) {
|
|
28
|
+
return res.status(409).json({ message: "Email already registered." });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const hashedPassword = await bcrypt.hash(password, 10);
|
|
32
|
+
const result = await createUser({ username: username.trim(), email: emailNorm, password: hashedPassword });
|
|
33
|
+
return res.status(201).json({
|
|
34
|
+
message: "Registration successful.",
|
|
35
|
+
userId: result.insertId,
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const login = async (req, res) => {
|
|
40
|
+
const { username, password } = req.body;
|
|
41
|
+
if (!username || !password) {
|
|
42
|
+
return res.status(400).json({ message: "Username and password are required." });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const users = await findUserByUsername(username.trim());
|
|
46
|
+
if (!users.length) {
|
|
47
|
+
return res.status(401).json({ message: "Invalid credentials." });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const user = users[0];
|
|
51
|
+
const match = await bcrypt.compare(password, user.password);
|
|
52
|
+
if (!match) {
|
|
53
|
+
return res.status(401).json({ message: "Invalid credentials." });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const token = createAccessToken({
|
|
57
|
+
userId: user.user_id,
|
|
58
|
+
username: user.username,
|
|
59
|
+
role: user.role,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return res.json({
|
|
63
|
+
message: "Login successful.",
|
|
64
|
+
token,
|
|
65
|
+
user: { user_id: user.user_id, username: user.username, role: user.role },
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const forgotPassword = async (req, res) => {
|
|
70
|
+
try {
|
|
71
|
+
const { email, newPassword, confirmPassword } = req.body;
|
|
72
|
+
if (!email) {
|
|
73
|
+
return res.status(400).json({ success: false, message: "Email is required." });
|
|
74
|
+
}
|
|
75
|
+
if (!newPassword) {
|
|
76
|
+
return res.status(400).json({ success: false, message: "New password is required." });
|
|
77
|
+
}
|
|
78
|
+
if (!confirmPassword) {
|
|
79
|
+
return res.status(400).json({ success: false, message: "Confirm password is required." });
|
|
80
|
+
}
|
|
81
|
+
if (newPassword !== confirmPassword) {
|
|
82
|
+
return res.status(400).json({
|
|
83
|
+
success: false,
|
|
84
|
+
message: "New password and confirm password must match.",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const emailNorm = normalizeEmail(email);
|
|
88
|
+
const rows = await findUserByEmail(emailNorm);
|
|
89
|
+
if (!rows.length) {
|
|
90
|
+
return res.status(404).json({ success: false, message: "User not found" });
|
|
91
|
+
}
|
|
92
|
+
const hash = await bcrypt.hash(newPassword, 10);
|
|
93
|
+
await updatePasswordByEmail(emailNorm, hash);
|
|
94
|
+
return res.json({ success: true, message: "Password reset successfully" });
|
|
95
|
+
} catch {
|
|
96
|
+
return res.status(500).json({ success: false, message: "Server error." });
|
|
97
|
+
}
|
|
98
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as customerModel from "../models/customerModel.js";
|
|
2
|
+
|
|
3
|
+
export const getCustomers = async (req, res) => {
|
|
4
|
+
const { q } = req.query;
|
|
5
|
+
const customers = q
|
|
6
|
+
? await customerModel.searchCustomers(q)
|
|
7
|
+
: await customerModel.getAllCustomers();
|
|
8
|
+
res.json(customers);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const addCustomer = async (req, res) => {
|
|
12
|
+
const result = await customerModel.createCustomer(req.body);
|
|
13
|
+
res
|
|
14
|
+
.status(201)
|
|
15
|
+
.json({ message: "Customer created.", customerId: result.insertId });
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const editCustomer = async (req, res) => {
|
|
19
|
+
await customerModel.updateCustomer(req.params.id, req.body);
|
|
20
|
+
res.json({ message: "Customer updated." });
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const removeCustomer = async (req, res) => {
|
|
24
|
+
await customerModel.deleteCustomer(req.params.id);
|
|
25
|
+
res.json({ message: "Customer deleted." });
|
|
26
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as productModel from "../models/productModel.js";
|
|
2
|
+
|
|
3
|
+
export const getProducts = async (_req, res) => {
|
|
4
|
+
const products = await productModel.getAllProducts();
|
|
5
|
+
res.json(products);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const addProduct = async (req, res) => {
|
|
9
|
+
const result = await productModel.createProduct(req.body);
|
|
10
|
+
res.status(201).json({ message: "Product created.", productId: result.insertId });
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const editProduct = async (req, res) => {
|
|
14
|
+
await productModel.updateProduct(req.params.id, req.body);
|
|
15
|
+
res.json({ message: "Product updated." });
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const removeProduct = async (req, res) => {
|
|
19
|
+
await productModel.deleteProduct(req.params.id);
|
|
20
|
+
res.json({ message: "Product deleted." });
|
|
21
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as reportModel from "../models/reportModel.js";
|
|
2
|
+
|
|
3
|
+
export const dashboardSummary = async (_req, res) => {
|
|
4
|
+
const [summary] = await reportModel.getDashboardSummary();
|
|
5
|
+
res.json(summary);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const dailySales = async (req, res) => {
|
|
9
|
+
const { date } = req.query;
|
|
10
|
+
const rows = await reportModel.getDailySalesReport(date);
|
|
11
|
+
res.json(rows);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const monthlySales = async (req, res) => {
|
|
15
|
+
const { startDate, endDate } = req.query;
|
|
16
|
+
const rows = await reportModel.getMonthlySalesReport(startDate, endDate);
|
|
17
|
+
res.json(rows);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const productStock = async (_req, res) => {
|
|
21
|
+
const rows = await reportModel.getProductStockReport();
|
|
22
|
+
res.json(rows);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const customerPurchases = async (req, res) => {
|
|
26
|
+
const { customerName = "" } = req.query;
|
|
27
|
+
const rows = await reportModel.getCustomerPurchasesReport(customerName);
|
|
28
|
+
res.json(rows);
|
|
29
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as saleModel from "../models/saleModel.js";
|
|
2
|
+
|
|
3
|
+
export const getSales = async (_req, res) => {
|
|
4
|
+
const sales = await saleModel.getSales();
|
|
5
|
+
res.json(sales);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const recordSale = async (req, res) => {
|
|
9
|
+
const saleId = await saleModel.createSale(req.body);
|
|
10
|
+
res.status(201).json({ message: "Sale recorded.", saleId });
|
|
11
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import jwt from "jsonwebtoken";
|
|
2
|
+
|
|
3
|
+
const authMiddleware = (req, res, next) => {
|
|
4
|
+
const authHeader = req.headers.authorization;
|
|
5
|
+
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
6
|
+
return res.status(401).json({ message: "Missing authorization token." });
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const token = authHeader.split(" ")[1];
|
|
10
|
+
try {
|
|
11
|
+
const decoded = jwt.verify(
|
|
12
|
+
token,
|
|
13
|
+
process.env.JWT_SECRET || "smartshop_student_project_secret"
|
|
14
|
+
);
|
|
15
|
+
req.user = decoded;
|
|
16
|
+
return next();
|
|
17
|
+
} catch {
|
|
18
|
+
return res.status(401).json({ message: "Invalid or expired token." });
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default authMiddleware;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { query } from "../config/db.js";
|
|
2
|
+
|
|
3
|
+
export const findUserByUsername = (username) =>
|
|
4
|
+
query(
|
|
5
|
+
"SELECT user_id, username, email, password, role FROM users WHERE username = ?",
|
|
6
|
+
[username]
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
export const findUserByEmail = (email) =>
|
|
10
|
+
query(
|
|
11
|
+
"SELECT user_id, username, email, password, role FROM users WHERE email = ?",
|
|
12
|
+
[email]
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export const createUser = ({ username, email, password, role = "student" }) =>
|
|
16
|
+
query("INSERT INTO users (username, email, password, role) VALUES (?, ?, ?, ?)", [
|
|
17
|
+
username,
|
|
18
|
+
email,
|
|
19
|
+
password,
|
|
20
|
+
role,
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
export const updatePasswordByEmail = (email, password) =>
|
|
24
|
+
query("UPDATE users SET password = ? WHERE email = ?", [password, email]);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import pool, { query } from "../config/db.js";
|
|
2
|
+
|
|
3
|
+
export const getAllCustomers = () =>
|
|
4
|
+
query("SELECT * FROM customers ORDER BY registration_date DESC");
|
|
5
|
+
|
|
6
|
+
export const searchCustomers = (term) =>
|
|
7
|
+
query(
|
|
8
|
+
`SELECT *
|
|
9
|
+
FROM customers
|
|
10
|
+
WHERE full_name LIKE ? OR phone_number LIKE ? OR email LIKE ?
|
|
11
|
+
ORDER BY registration_date DESC`,
|
|
12
|
+
[`%${term}%`, `%${term}%`, `%${term}%`]
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export const createCustomer = (payload) =>
|
|
16
|
+
query(
|
|
17
|
+
`INSERT INTO customers (full_name, phone_number, email, address, registration_date)
|
|
18
|
+
VALUES (?, ?, ?, ?, NOW())`,
|
|
19
|
+
[payload.fullName, payload.phoneNumber, payload.email, payload.address]
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
export const updateCustomer = (id, payload) =>
|
|
23
|
+
query(
|
|
24
|
+
`UPDATE customers
|
|
25
|
+
SET full_name = ?, phone_number = ?, email = ?, address = ?
|
|
26
|
+
WHERE customer_id = ?`,
|
|
27
|
+
[payload.fullName, payload.phoneNumber, payload.email, payload.address, id]
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
export const deleteCustomer = async (id) => {
|
|
31
|
+
const connection = await pool.getConnection();
|
|
32
|
+
try {
|
|
33
|
+
await connection.beginTransaction();
|
|
34
|
+
await connection.execute("DELETE FROM sales WHERE customer_id = ?", [id]);
|
|
35
|
+
await connection.execute("DELETE FROM customers WHERE customer_id = ?", [id]);
|
|
36
|
+
await connection.commit();
|
|
37
|
+
} catch (error) {
|
|
38
|
+
await connection.rollback();
|
|
39
|
+
throw error;
|
|
40
|
+
} finally {
|
|
41
|
+
connection.release();
|
|
42
|
+
}
|
|
43
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import pool, { query } from "../config/db.js";
|
|
2
|
+
|
|
3
|
+
export const getAllProducts = () =>
|
|
4
|
+
query("SELECT * FROM products ORDER BY created_at DESC");
|
|
5
|
+
|
|
6
|
+
export const createProduct = (payload) =>
|
|
7
|
+
query(
|
|
8
|
+
`INSERT INTO products (product_name, category, quantity, price, created_at)
|
|
9
|
+
VALUES (?, ?, ?, ?, NOW())`,
|
|
10
|
+
[payload.productName, payload.category, payload.quantity, payload.price]
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
export const updateProduct = (id, payload) =>
|
|
14
|
+
query(
|
|
15
|
+
`UPDATE products
|
|
16
|
+
SET product_name = ?, category = ?, quantity = ?, price = ?
|
|
17
|
+
WHERE product_id = ?`,
|
|
18
|
+
[payload.productName, payload.category, payload.quantity, payload.price, id]
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export const deleteProduct = async (id) => {
|
|
22
|
+
const connection = await pool.getConnection();
|
|
23
|
+
try {
|
|
24
|
+
await connection.beginTransaction();
|
|
25
|
+
await connection.execute("DELETE FROM sales WHERE product_id = ?", [id]);
|
|
26
|
+
await connection.execute("DELETE FROM products WHERE product_id = ?", [id]);
|
|
27
|
+
await connection.commit();
|
|
28
|
+
} catch (error) {
|
|
29
|
+
await connection.rollback();
|
|
30
|
+
throw error;
|
|
31
|
+
} finally {
|
|
32
|
+
connection.release();
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const getProductById = (id) =>
|
|
37
|
+
query("SELECT * FROM products WHERE product_id = ?", [id]);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { query } from "../config/db.js";
|
|
2
|
+
|
|
3
|
+
export const getDailySalesReport = (date) =>
|
|
4
|
+
query(
|
|
5
|
+
`SELECT s.sale_id, c.full_name AS customer_name, p.product_name, s.quantity,
|
|
6
|
+
s.unit_price, s.total_price, s.sale_date
|
|
7
|
+
FROM sales s
|
|
8
|
+
JOIN customers c ON c.customer_id = s.customer_id
|
|
9
|
+
JOIN products p ON p.product_id = s.product_id
|
|
10
|
+
WHERE DATE(s.sale_date) = ?
|
|
11
|
+
ORDER BY s.sale_date DESC`,
|
|
12
|
+
[date]
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export const getMonthlySalesReport = (startDate, endDate) =>
|
|
16
|
+
query(
|
|
17
|
+
`SELECT s.sale_id, c.full_name AS customer_name, p.product_name, s.quantity,
|
|
18
|
+
s.unit_price, s.total_price, s.sale_date
|
|
19
|
+
FROM sales s
|
|
20
|
+
JOIN customers c ON c.customer_id = s.customer_id
|
|
21
|
+
JOIN products p ON p.product_id = s.product_id
|
|
22
|
+
WHERE DATE(s.sale_date) BETWEEN ? AND ?
|
|
23
|
+
ORDER BY s.sale_date DESC`,
|
|
24
|
+
[startDate, endDate]
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
export const getProductStockReport = () =>
|
|
28
|
+
query(
|
|
29
|
+
`SELECT p.product_id, p.product_name, p.quantity AS available_stock,
|
|
30
|
+
COALESCE(SUM(s.quantity), 0) AS sold_stock
|
|
31
|
+
FROM products p
|
|
32
|
+
LEFT JOIN sales s ON s.product_id = p.product_id
|
|
33
|
+
GROUP BY p.product_id, p.product_name, p.quantity
|
|
34
|
+
ORDER BY p.product_name`
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
export const getCustomerPurchasesReport = (customerName) =>
|
|
38
|
+
query(
|
|
39
|
+
`SELECT s.sale_id, c.full_name AS customer_name, p.product_name, s.quantity,
|
|
40
|
+
s.unit_price, s.total_price, s.sale_date
|
|
41
|
+
FROM sales s
|
|
42
|
+
JOIN customers c ON c.customer_id = s.customer_id
|
|
43
|
+
JOIN products p ON p.product_id = s.product_id
|
|
44
|
+
WHERE c.full_name LIKE ?
|
|
45
|
+
ORDER BY s.sale_date DESC`,
|
|
46
|
+
[`%${customerName}%`]
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
export const getDashboardSummary = () =>
|
|
50
|
+
query(
|
|
51
|
+
`SELECT
|
|
52
|
+
(SELECT COUNT(*) FROM products) AS total_products,
|
|
53
|
+
(SELECT COUNT(*) FROM customers) AS total_customers,
|
|
54
|
+
(SELECT COUNT(*) FROM sales) AS total_sales,
|
|
55
|
+
(SELECT COALESCE(SUM(total_price), 0) FROM sales) AS total_revenue`
|
|
56
|
+
);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import pool, { query } from "../config/db.js";
|
|
2
|
+
|
|
3
|
+
export const getSales = () =>
|
|
4
|
+
query(
|
|
5
|
+
`SELECT s.sale_id, s.quantity, s.unit_price, s.total_price, s.sale_date,
|
|
6
|
+
c.customer_id, c.full_name AS customer_name,
|
|
7
|
+
p.product_id, p.product_name
|
|
8
|
+
FROM sales s
|
|
9
|
+
JOIN customers c ON c.customer_id = s.customer_id
|
|
10
|
+
JOIN products p ON p.product_id = s.product_id
|
|
11
|
+
ORDER BY s.sale_date DESC`
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
export const createSale = async ({ customerId, productId, quantity }) => {
|
|
15
|
+
const connection = await pool.getConnection();
|
|
16
|
+
try {
|
|
17
|
+
await connection.beginTransaction();
|
|
18
|
+
|
|
19
|
+
const [products] = await connection.execute(
|
|
20
|
+
"SELECT product_id, product_name, price, quantity FROM products WHERE product_id = ? FOR UPDATE",
|
|
21
|
+
[productId]
|
|
22
|
+
);
|
|
23
|
+
if (!products.length) {
|
|
24
|
+
throw new Error("Product not found.");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const product = products[0];
|
|
28
|
+
if (Number(product.quantity) < Number(quantity)) {
|
|
29
|
+
throw new Error("Insufficient stock.");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const unitPrice = Number(product.price);
|
|
33
|
+
const totalPrice = unitPrice * Number(quantity);
|
|
34
|
+
|
|
35
|
+
const [result] = await connection.execute(
|
|
36
|
+
`INSERT INTO sales (customer_id, product_id, quantity, unit_price, total_price, sale_date)
|
|
37
|
+
VALUES (?, ?, ?, ?, ?, NOW())`,
|
|
38
|
+
[customerId, productId, quantity, unitPrice, totalPrice]
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
await connection.execute(
|
|
42
|
+
"UPDATE products SET quantity = quantity - ? WHERE product_id = ?",
|
|
43
|
+
[quantity, productId]
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
await connection.commit();
|
|
47
|
+
return result.insertId;
|
|
48
|
+
} catch (error) {
|
|
49
|
+
await connection.rollback();
|
|
50
|
+
throw error;
|
|
51
|
+
} finally {
|
|
52
|
+
connection.release();
|
|
53
|
+
}
|
|
54
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import { login, register, forgotPassword } from "../controllers/authController.js";
|
|
3
|
+
|
|
4
|
+
const router = Router();
|
|
5
|
+
|
|
6
|
+
router.post("/register", register);
|
|
7
|
+
router.post("/login", login);
|
|
8
|
+
router.post("/forgot-password", forgotPassword);
|
|
9
|
+
|
|
10
|
+
export default router;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import {
|
|
3
|
+
addCustomer,
|
|
4
|
+
editCustomer,
|
|
5
|
+
getCustomers,
|
|
6
|
+
removeCustomer,
|
|
7
|
+
} from "../controllers/customerController.js";
|
|
8
|
+
|
|
9
|
+
const router = Router();
|
|
10
|
+
|
|
11
|
+
router.get("/", getCustomers);
|
|
12
|
+
router.post("/", addCustomer);
|
|
13
|
+
router.put("/:id", editCustomer);
|
|
14
|
+
router.delete("/:id", removeCustomer);
|
|
15
|
+
|
|
16
|
+
export default router;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import {
|
|
3
|
+
addProduct,
|
|
4
|
+
editProduct,
|
|
5
|
+
getProducts,
|
|
6
|
+
removeProduct,
|
|
7
|
+
} from "../controllers/productController.js";
|
|
8
|
+
|
|
9
|
+
const router = Router();
|
|
10
|
+
|
|
11
|
+
router.get("/", getProducts);
|
|
12
|
+
router.post("/", addProduct);
|
|
13
|
+
router.put("/:id", editProduct);
|
|
14
|
+
router.delete("/:id", removeProduct);
|
|
15
|
+
|
|
16
|
+
export default router;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import {
|
|
3
|
+
customerPurchases,
|
|
4
|
+
dailySales,
|
|
5
|
+
dashboardSummary,
|
|
6
|
+
monthlySales,
|
|
7
|
+
productStock,
|
|
8
|
+
} from "../controllers/reportController.js";
|
|
9
|
+
|
|
10
|
+
const router = Router();
|
|
11
|
+
|
|
12
|
+
router.get("/dashboard", dashboardSummary);
|
|
13
|
+
router.get("/daily-sales", dailySales);
|
|
14
|
+
router.get("/monthly-sales", monthlySales);
|
|
15
|
+
router.get("/product-stock", productStock);
|
|
16
|
+
router.get("/customer-purchases", customerPurchases);
|
|
17
|
+
|
|
18
|
+
export default router;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import app from "./app.js";
|
|
2
|
+
import { checkDatabaseConnection } from "./config/db.js";
|
|
3
|
+
|
|
4
|
+
const PORT = Number(process.env.PORT || 5000);
|
|
5
|
+
|
|
6
|
+
const startServer = async () => {
|
|
7
|
+
const dbStatus = await checkDatabaseConnection();
|
|
8
|
+
|
|
9
|
+
app.listen(PORT, () => {
|
|
10
|
+
// eslint-disable-next-line no-console
|
|
11
|
+
console.log(`SMS backend running on port ${PORT}`);
|
|
12
|
+
if (!dbStatus.ok) {
|
|
13
|
+
// eslint-disable-next-line no-console
|
|
14
|
+
console.error("[SERVER] API started, but database connection failed.");
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
startServer();
|