create-myexam-app 1.0.21 → 1.0.23
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 +25 -17
- package/package.json +1 -1
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/README.md +84 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/.env +3 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/config/db.js +13 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/controllers/authController.js +115 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/controllers/employeeController.js +97 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/controllers/payrollController.js +113 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/controllers/reportController.js +35 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/middleware/authMiddleware.js +9 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/models/Employee.js +52 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/models/Payroll.js +50 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/models/User.js +19 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/package-lock.json +1509 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/package.json +19 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/routes/authRoutes.js +18 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/routes/employeeRoutes.js +19 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/routes/payrollRoutes.js +19 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/routes/reportRoutes.js +9 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/server.js +71 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/index.html +12 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/package-lock.json +2888 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/package.json +23 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/postcss.config.js +6 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/App.jsx +57 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/apiClient.js +16 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/authApi.js +26 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/employeeApi.js +26 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/payrollApi.js +26 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/reportApi.js +6 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/components/Header.jsx +17 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/components/Layout.jsx +17 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/components/Message.jsx +15 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/components/ProtectedRoute.jsx +41 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/components/Sidebar.jsx +38 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/index.css +30 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/main.jsx +13 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/DashboardPage.jsx +64 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/EmployeePage.jsx +166 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/LoginPage.jsx +73 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/PayrollPage.jsx +198 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/RecoverPasswordPage.jsx +69 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/RegisterPage.jsx +69 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/ReportsPage.jsx +113 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/tailwind.config.js +13 -0
- package/projects/EPMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/vite.config.js +9 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/README.md +106 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/REPORT/01_Introduction.md +8 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/REPORT/02_Problem_Statement.md +12 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/REPORT/03_Objectives.md +17 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/REPORT/04_Technologies_Used.md +23 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/REPORT/05_ERD.md +60 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/REPORT/06_Database_Design.md +71 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/REPORT/07_System_Architecture.md +28 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/REPORT/08_API_Documentation.md +43 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/REPORT/09_Testing.md +43 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/REPORT/10_Challenges.md +12 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/REPORT/11_Conclusion.md +8 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/.env.example +4 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/config/db.js +16 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/controllers/deliveryController.js +145 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/controllers/shipmentController.js +149 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/controllers/supplierController.js +56 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/controllers/userController.js +158 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/middleware/authMiddleware.js +9 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/models/Delivery.js +34 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/models/Shipment.js +34 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/models/Supplier.js +38 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/models/User.js +21 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/package-lock.json +1540 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/package.json +22 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/routes/deliveryRoutes.js +11 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/routes/shipmentRoutes.js +11 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/routes/supplierRoutes.js +9 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/routes/userRoutes.js +11 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/server.js +70 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/.env.example +2 -0
- package/projects/{SCMS/frontend → SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project}/index.html +2 -2
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/package-lock.json +2944 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/package.json +23 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/postcss.config.js +6 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/App.jsx +72 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/apiClient.js +14 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/deliveryApi.js +17 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/shipmentApi.js +17 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/supplierApi.js +9 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/userApi.js +21 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/components/Layout.jsx +16 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/components/Message.jsx +15 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/components/PageHeader.jsx +12 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/components/Sidebar.jsx +40 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/main.jsx +13 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/Dashboard.jsx +62 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/Delivery.jsx +212 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/Login.jsx +158 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/Logout.jsx +24 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/Reports.jsx +221 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/Shipment.jsx +212 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/Supplier.jsx +118 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/styles.css +27 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/tailwind.config.js +8 -0
- package/projects/SCMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/vite.config.js +6 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/README.md +84 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/.env +3 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/config/db.js +13 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/controllers/productController.js +29 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/controllers/reportController.js +52 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/controllers/stockTransactionController.js +128 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/controllers/userController.js +115 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/controllers/warehouseController.js +29 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/middleware/authMiddleware.js +9 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/models/Product.js +44 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/models/StockTransaction.js +33 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/models/User.js +19 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/models/Warehouse.js +25 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/package-lock.json +1509 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/package.json +19 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/routes/productRoutes.js +10 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/routes/reportRoutes.js +9 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/routes/stockTransactionRoutes.js +17 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/routes/userRoutes.js +18 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/routes/warehouseRoutes.js +10 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/backend-project/server.js +73 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/index.html +12 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/package-lock.json +2888 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/package.json +23 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/postcss.config.js +6 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/App.jsx +66 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/apiClient.js +16 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/productApi.js +11 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/reportApi.js +6 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/transactionApi.js +21 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/userApi.js +26 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/api/warehouseApi.js +11 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/components/Header.jsx +17 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/components/Layout.jsx +17 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/components/Message.jsx +15 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/components/ProtectedRoute.jsx +41 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/components/Sidebar.jsx +39 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/index.css +30 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/main.jsx +13 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/DashboardPage.jsx +64 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/LoginPage.jsx +73 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/ProductPage.jsx +107 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/RecoverPasswordPage.jsx +69 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/RegisterPage.jsx +69 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/ReportsPage.jsx +152 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/TransactionPage.jsx +195 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/src/pages/WarehousePage.jsx +93 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/tailwind.config.js +13 -0
- package/projects/SHMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026/frontend-project/vite.config.js +9 -0
- package/projects/SMS-/frontend-project/src/pages/Reports.jsx +179 -23
- package/projects/SRMS/frontend/src/pages/Reports.jsx +170 -58
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/README.md +49 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/backend-project/.env +3 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/backend-project/middleware/authMiddleware.js +19 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/backend-project/models/Customer.js +11 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/backend-project/models/Product.js +10 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/backend-project/models/Sale.js +19 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/backend-project/models/User.js +8 -0
- package/projects/{SCMS/backend → SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/backend-project}/package-lock.json +1609 -2190
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/backend-project/package.json +20 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/backend-project/routes/authRoutes.js +75 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/backend-project/routes/customerRoutes.js +42 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/backend-project/routes/productRoutes.js +41 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/backend-project/routes/reportRoutes.js +129 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/backend-project/routes/saleRoutes.js +107 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/backend-project/server.js +49 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/dist/assets/index-DZxY56Bj.js +75 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/dist/assets/index-J8MKb3Fq.css +1 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/dist/index.html +13 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/index.html +12 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/package-lock.json +2029 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/package.json +21 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/src/App.jsx +77 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/src/index.css +333 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/src/main.jsx +10 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/src/pages/Customers.jsx +85 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/src/pages/Dashboard.jsx +75 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/src/pages/Login.jsx +65 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/src/pages/Products.jsx +91 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/src/pages/Register.jsx +82 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/src/pages/Reports.jsx +138 -0
- package/projects/SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project/src/pages/Sales.jsx +154 -0
- package/projects/{SCMS/frontend → SRMS(Ely)/KALIWABO_SHEMA_ELYSEE_National_Practical_Examination_2026(/frontend-project}/vite.config.js +5 -3
- package/projects/SCMS/backend/.env +0 -5
- package/projects/SCMS/backend/config/db.js +0 -12
- package/projects/SCMS/backend/controllers/authController.js +0 -90
- package/projects/SCMS/backend/controllers/deliveryController.js +0 -79
- package/projects/SCMS/backend/controllers/productController.js +0 -74
- package/projects/SCMS/backend/controllers/reportsController.js +0 -77
- package/projects/SCMS/backend/controllers/shipmentController.js +0 -80
- package/projects/SCMS/backend/controllers/supplierController.js +0 -58
- package/projects/SCMS/backend/middleware/auth.js +0 -32
- package/projects/SCMS/backend/models/User.js +0 -28
- package/projects/SCMS/backend/models/delivery.js +0 -33
- package/projects/SCMS/backend/models/product.js +0 -43
- package/projects/SCMS/backend/models/shipment.js +0 -34
- package/projects/SCMS/backend/models/supplier.js +0 -36
- package/projects/SCMS/backend/package.json +0 -23
- package/projects/SCMS/backend/routes/SupplierRoutes.js +0 -15
- package/projects/SCMS/backend/routes/authRoutes.js +0 -11
- package/projects/SCMS/backend/routes/deliveryRoutes.js +0 -18
- package/projects/SCMS/backend/routes/productRoutes.js +0 -15
- package/projects/SCMS/backend/routes/protectedRoutes.js +0 -10
- package/projects/SCMS/backend/routes/reportsRoutes.js +0 -8
- package/projects/SCMS/backend/routes/shipmentRoutes.js +0 -18
- package/projects/SCMS/backend/server.js +0 -35
- package/projects/SCMS/frontend/README.md +0 -16
- package/projects/SCMS/frontend/eslint.config.js +0 -21
- package/projects/SCMS/frontend/package-lock.json +0 -3053
- package/projects/SCMS/frontend/package.json +0 -31
- package/projects/SCMS/frontend/public/favicon.svg +0 -1
- package/projects/SCMS/frontend/src/App.jsx +0 -35
- package/projects/SCMS/frontend/src/components/DashboardLayout.jsx +0 -103
- package/projects/SCMS/frontend/src/components/ProtectedRoute.jsx +0 -30
- package/projects/SCMS/frontend/src/index.css +0 -114
- package/projects/SCMS/frontend/src/main.jsx +0 -10
- package/projects/SCMS/frontend/src/pages/DashboardHome.jsx +0 -34
- package/projects/SCMS/frontend/src/pages/Delivery.jsx +0 -183
- package/projects/SCMS/frontend/src/pages/Login.jsx +0 -81
- package/projects/SCMS/frontend/src/pages/Profile.jsx +0 -62
- package/projects/SCMS/frontend/src/pages/Register.jsx +0 -110
- package/projects/SCMS/frontend/src/pages/Reports.jsx +0 -94
- package/projects/SCMS/frontend/src/pages/Shipment.jsx +0 -182
- package/projects/SCMS/frontend/src/pages/Supplier.jsx +0 -165
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
|
|
5
|
+
var emptyProduct = { productCode: '', productName: '', quantitySold: '', unitPrice: '' };
|
|
6
|
+
|
|
7
|
+
function Products(props) {
|
|
8
|
+
var productsState = useState([]);
|
|
9
|
+
var products = productsState[0];
|
|
10
|
+
var setProducts = productsState[1];
|
|
11
|
+
var formState = useState(emptyProduct);
|
|
12
|
+
var form = formState[0];
|
|
13
|
+
var setForm = formState[1];
|
|
14
|
+
|
|
15
|
+
var token = props.session ? props.session.token : '';
|
|
16
|
+
var headers = { Authorization: 'Bearer ' + token };
|
|
17
|
+
|
|
18
|
+
function load() {
|
|
19
|
+
axios.get(props.API + '/products', { headers: headers })
|
|
20
|
+
.then(function(res) {
|
|
21
|
+
setProducts(res.data);
|
|
22
|
+
})
|
|
23
|
+
.catch(function() {});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
useEffect(function() { load(); }, []);
|
|
27
|
+
|
|
28
|
+
function submit() {
|
|
29
|
+
if (!form.productCode || !form.productName || !form.quantitySold || !form.unitPrice) {
|
|
30
|
+
props.setNotice('All fields are required');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
axios.post(props.API + '/products', {
|
|
34
|
+
productCode: form.productCode,
|
|
35
|
+
productName: form.productName,
|
|
36
|
+
quantitySold: Number(form.quantitySold),
|
|
37
|
+
unitPrice: Number(form.unitPrice)
|
|
38
|
+
}, { headers: headers })
|
|
39
|
+
.then(function() {
|
|
40
|
+
setForm(emptyProduct);
|
|
41
|
+
return load();
|
|
42
|
+
})
|
|
43
|
+
.then(function() {
|
|
44
|
+
props.setNotice('Product saved successfully');
|
|
45
|
+
})
|
|
46
|
+
.catch(function(err) {
|
|
47
|
+
var msg = 'Could not save';
|
|
48
|
+
if (err.response && err.response.data) {
|
|
49
|
+
msg = err.response.data.message || err.response.data.error || msg;
|
|
50
|
+
}
|
|
51
|
+
props.setNotice(msg);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<main className="page">
|
|
57
|
+
<div className="page-title"><h2>Products</h2><p>Manage product records.</p></div>
|
|
58
|
+
<section className="form-grid four">
|
|
59
|
+
<input placeholder="Product Code" value={form.productCode} onChange={function(e) { setForm({ productCode: e.target.value, productName: form.productName, quantitySold: form.quantitySold, unitPrice: form.unitPrice }); }} />
|
|
60
|
+
<input placeholder="Product Name" value={form.productName} onChange={function(e) { setForm({ productCode: form.productCode, productName: e.target.value, quantitySold: form.quantitySold, unitPrice: form.unitPrice }); }} />
|
|
61
|
+
<input type="number" placeholder="Quantity Sold" value={form.quantitySold} onChange={function(e) { setForm({ productCode: form.productCode, productName: form.productName, quantitySold: e.target.value, unitPrice: form.unitPrice }); }} />
|
|
62
|
+
<input type="number" placeholder="Unit Price" value={form.unitPrice} onChange={function(e) { setForm({ productCode: form.productCode, productName: form.productName, quantitySold: form.quantitySold, unitPrice: e.target.value }); }} />
|
|
63
|
+
<button onClick={submit}>Submit Data</button>
|
|
64
|
+
</section>
|
|
65
|
+
<div className="table-wrap">
|
|
66
|
+
<table>
|
|
67
|
+
<thead>
|
|
68
|
+
<tr>
|
|
69
|
+
<th>Code</th><th>Name</th><th>Quantity Sold</th><th>Unit Price</th><th>Total</th>
|
|
70
|
+
</tr>
|
|
71
|
+
</thead>
|
|
72
|
+
<tbody>
|
|
73
|
+
{products.length === 0 ? (
|
|
74
|
+
<tr><td colSpan="5" style={{ textAlign: 'center', color: '#94a3b8', padding: 20 }}>No products found</td></tr>
|
|
75
|
+
) : products.map(function(p) {
|
|
76
|
+
return (
|
|
77
|
+
<tr key={p._id}>
|
|
78
|
+
<td>{p.productCode}</td><td>{p.productName}</td>
|
|
79
|
+
<td>{p.quantitySold}</td><td>{p.unitPrice.toLocaleString()} FRW</td>
|
|
80
|
+
<td>{(p.quantitySold * p.unitPrice).toLocaleString()} FRW</td>
|
|
81
|
+
</tr>
|
|
82
|
+
);
|
|
83
|
+
})}
|
|
84
|
+
</tbody>
|
|
85
|
+
</table>
|
|
86
|
+
</div>
|
|
87
|
+
</main>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export default Products;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Link, useNavigate } from 'react-router-dom';
|
|
4
|
+
import axios from 'axios';
|
|
5
|
+
|
|
6
|
+
var API = 'http://localhost:5000/api';
|
|
7
|
+
|
|
8
|
+
function Register(props) {
|
|
9
|
+
var navigate = useNavigate();
|
|
10
|
+
var formState = useState({ username: '', password: '', confirmPassword: '' });
|
|
11
|
+
var form = formState[0];
|
|
12
|
+
var setForm = formState[1];
|
|
13
|
+
var errorState = useState('');
|
|
14
|
+
var error = errorState[0];
|
|
15
|
+
var setError = errorState[1];
|
|
16
|
+
|
|
17
|
+
function submit(e) {
|
|
18
|
+
e.preventDefault();
|
|
19
|
+
setError('');
|
|
20
|
+
if (!form.username || !form.password) {
|
|
21
|
+
setError('All fields are required');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (form.password !== form.confirmPassword) {
|
|
25
|
+
setError('Passwords do not match');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (form.password.length < 4) {
|
|
29
|
+
setError('Password must be at least 4 characters');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
axios.post(API + '/auth/register', {
|
|
33
|
+
username: form.username,
|
|
34
|
+
password: form.password
|
|
35
|
+
})
|
|
36
|
+
.then(function(res) {
|
|
37
|
+
props.onLogin(res.data);
|
|
38
|
+
navigate('/dashboard');
|
|
39
|
+
})
|
|
40
|
+
.catch(function(err) {
|
|
41
|
+
var msg = 'Registration failed';
|
|
42
|
+
if (err.response && err.response.data && err.response.data.message) {
|
|
43
|
+
msg = err.response.data.message;
|
|
44
|
+
}
|
|
45
|
+
setError(msg);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<main className="auth-page">
|
|
51
|
+
<section className="auth-card">
|
|
52
|
+
<h1>Create Account</h1>
|
|
53
|
+
<form onSubmit={submit} className="auth-form">
|
|
54
|
+
{error && <p className="form-error">{error}</p>}
|
|
55
|
+
<input
|
|
56
|
+
placeholder="Username"
|
|
57
|
+
value={form.username}
|
|
58
|
+
onChange={function(e) { setForm({ username: e.target.value, password: form.password, confirmPassword: form.confirmPassword }); }}
|
|
59
|
+
/>
|
|
60
|
+
<input
|
|
61
|
+
type="password"
|
|
62
|
+
placeholder="Password"
|
|
63
|
+
value={form.password}
|
|
64
|
+
onChange={function(e) { setForm({ username: form.username, password: e.target.value, confirmPassword: form.confirmPassword }); }}
|
|
65
|
+
/>
|
|
66
|
+
<input
|
|
67
|
+
type="password"
|
|
68
|
+
placeholder="Confirm Password"
|
|
69
|
+
value={form.confirmPassword}
|
|
70
|
+
onChange={function(e) { setForm({ username: form.username, password: form.password, confirmPassword: e.target.value }); }}
|
|
71
|
+
/>
|
|
72
|
+
<button type="submit">Register</button>
|
|
73
|
+
<div className="auth-links">
|
|
74
|
+
<Link to="/login">Back to Login</Link>
|
|
75
|
+
</div>
|
|
76
|
+
</form>
|
|
77
|
+
</section>
|
|
78
|
+
</main>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export default Register;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
|
|
5
|
+
function Reports(props) {
|
|
6
|
+
var typeState = useState('daily');
|
|
7
|
+
var reportType = typeState[0];
|
|
8
|
+
var setReportType = typeState[1];
|
|
9
|
+
var dataState = useState(null);
|
|
10
|
+
var reportData = dataState[0];
|
|
11
|
+
var setReportData = dataState[1];
|
|
12
|
+
var loadingState = useState(false);
|
|
13
|
+
var loading = loadingState[0];
|
|
14
|
+
var setLoading = loadingState[1];
|
|
15
|
+
|
|
16
|
+
var now = new Date();
|
|
17
|
+
var dateStr = now.getFullYear() + '-' + (now.getMonth() + 1 < 10 ? '0' + (now.getMonth() + 1) : now.getMonth() + 1) + '-' + (now.getDate() < 10 ? '0' + now.getDate() : now.getDate());
|
|
18
|
+
var monthStr = now.getFullYear() + '-' + (now.getMonth() + 1 < 10 ? '0' + (now.getMonth() + 1) : now.getMonth() + 1);
|
|
19
|
+
|
|
20
|
+
var dateInputState = useState(dateStr);
|
|
21
|
+
var dateInput = dateInputState[0];
|
|
22
|
+
var setDateInput = dateInputState[1];
|
|
23
|
+
var monthInputState = useState(monthStr);
|
|
24
|
+
var monthInput = monthInputState[0];
|
|
25
|
+
var setMonthInput = monthInputState[1];
|
|
26
|
+
|
|
27
|
+
var token = props.session ? props.session.token : '';
|
|
28
|
+
var headers = { Authorization: 'Bearer ' + token };
|
|
29
|
+
|
|
30
|
+
function fetchReport() {
|
|
31
|
+
setLoading(true);
|
|
32
|
+
setReportData(null);
|
|
33
|
+
|
|
34
|
+
var url;
|
|
35
|
+
var params;
|
|
36
|
+
if (reportType === 'daily') {
|
|
37
|
+
url = props.API + '/reports/daily';
|
|
38
|
+
params = { date: dateInput };
|
|
39
|
+
} else if (reportType === 'weekly') {
|
|
40
|
+
url = props.API + '/reports/weekly';
|
|
41
|
+
params = { date: dateInput };
|
|
42
|
+
} else {
|
|
43
|
+
url = props.API + '/reports/monthly';
|
|
44
|
+
var parts = monthInput.split('-');
|
|
45
|
+
params = { year: parts[0], month: parts[1] };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
axios.get(url, { headers: headers, params: params })
|
|
49
|
+
.then(function(res) {
|
|
50
|
+
setReportData(res.data);
|
|
51
|
+
})
|
|
52
|
+
.catch(function(err) {
|
|
53
|
+
console.error('Report error:', err);
|
|
54
|
+
})
|
|
55
|
+
.then(function() {
|
|
56
|
+
setLoading(false);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function dateText(d) {
|
|
61
|
+
return d ? new Date(d).toLocaleDateString() : '-';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
var types = [
|
|
65
|
+
{ key: 'daily', label: 'Daily' },
|
|
66
|
+
{ key: 'weekly', label: 'Weekly' },
|
|
67
|
+
{ key: 'monthly', label: 'Monthly' },
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<main className="page">
|
|
72
|
+
<div className="page-title"><h2>Reports</h2><p>Generate sales reports.</p></div>
|
|
73
|
+
|
|
74
|
+
<section className="report-filters">
|
|
75
|
+
{types.map(function(t) {
|
|
76
|
+
return React.createElement('button', {
|
|
77
|
+
key: t.key,
|
|
78
|
+
onClick: function() { setReportType(t.key); },
|
|
79
|
+
style: {
|
|
80
|
+
background: reportType === t.key ? '#1E3A8A' : '#e2e8f0',
|
|
81
|
+
color: reportType === t.key ? 'white' : '#475569'
|
|
82
|
+
}
|
|
83
|
+
}, t.label);
|
|
84
|
+
})}
|
|
85
|
+
{(reportType === 'daily' || reportType === 'weekly') ? React.createElement('input', { type: 'date', value: dateInput, onChange: function(e) { setDateInput(e.target.value); } }) : null}
|
|
86
|
+
{reportType === 'monthly' ? React.createElement('input', { type: 'month', value: monthInput, onChange: function(e) { setMonthInput(e.target.value); } }) : null}
|
|
87
|
+
<button onClick={fetchReport} disabled={loading}>{loading ? 'Generating...' : 'Generate Report'}</button>
|
|
88
|
+
{reportData ? React.createElement('button', { className: 'no-print', onClick: function() { window.print(); } }, '🖨️ Print') : null}
|
|
89
|
+
</section>
|
|
90
|
+
|
|
91
|
+
{reportData ? (
|
|
92
|
+
<div>
|
|
93
|
+
<section className="report-summary">
|
|
94
|
+
<div className="report-stat">
|
|
95
|
+
<span>Total Transactions</span>
|
|
96
|
+
<strong>{reportData.totalTransactions}</strong>
|
|
97
|
+
</div>
|
|
98
|
+
<div className="report-stat">
|
|
99
|
+
<span>Total Revenue</span>
|
|
100
|
+
<strong>{reportData.totalRevenue.toLocaleString()} FRW</strong>
|
|
101
|
+
</div>
|
|
102
|
+
<div className="report-stat">
|
|
103
|
+
<span>Average per Sale</span>
|
|
104
|
+
<strong>{reportData.totalTransactions > 0 ? (reportData.totalRevenue / reportData.totalTransactions).toLocaleString() : '0'} FRW</strong>
|
|
105
|
+
</div>
|
|
106
|
+
</section>
|
|
107
|
+
|
|
108
|
+
<div className="table-wrap">
|
|
109
|
+
<table>
|
|
110
|
+
<thead>
|
|
111
|
+
<tr>
|
|
112
|
+
<th>Invoice</th><th>Date</th><th>Customer</th><th>Payment</th><th>Amount</th>
|
|
113
|
+
</tr>
|
|
114
|
+
</thead>
|
|
115
|
+
<tbody>
|
|
116
|
+
{reportData.sales.length === 0 ? (
|
|
117
|
+
<tr><td colSpan="5" style={{ textAlign: 'center', color: '#94a3b8', padding: 20 }}>No sales found</td></tr>
|
|
118
|
+
) : reportData.sales.map(function(s) {
|
|
119
|
+
return (
|
|
120
|
+
<tr key={s._id}>
|
|
121
|
+
<td>{s.invoiceNumber}</td>
|
|
122
|
+
<td>{dateText(s.salesDate)}</td>
|
|
123
|
+
<td>{s.customer ? s.customer.firstName + ' ' + s.customer.lastName : 'N/A'}</td>
|
|
124
|
+
<td>{s.paymentMethod}</td>
|
|
125
|
+
<td>{s.totalAmountPaid.toLocaleString()} FRW</td>
|
|
126
|
+
</tr>
|
|
127
|
+
);
|
|
128
|
+
})}
|
|
129
|
+
</tbody>
|
|
130
|
+
</table>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
) : null}
|
|
134
|
+
</main>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export default Reports;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
|
|
5
|
+
var emptySale = { invoiceNumber: '', salesDate: '', paymentMethod: 'Cash', totalAmountPaid: '', customer: '' };
|
|
6
|
+
|
|
7
|
+
function Sales(props) {
|
|
8
|
+
var salesState = useState([]);
|
|
9
|
+
var sales = salesState[0];
|
|
10
|
+
var setSales = salesState[1];
|
|
11
|
+
var customersState = useState([]);
|
|
12
|
+
var customers = customersState[0];
|
|
13
|
+
var setCustomers = customersState[1];
|
|
14
|
+
var formState = useState(emptySale);
|
|
15
|
+
var form = formState[0];
|
|
16
|
+
var setForm = formState[1];
|
|
17
|
+
var editIdState = useState('');
|
|
18
|
+
var editId = editIdState[0];
|
|
19
|
+
var setEditId = editIdState[1];
|
|
20
|
+
|
|
21
|
+
var token = props.session ? props.session.token : '';
|
|
22
|
+
var headers = { Authorization: 'Bearer ' + token };
|
|
23
|
+
|
|
24
|
+
function load() {
|
|
25
|
+
Promise.all([
|
|
26
|
+
axios.get(props.API + '/sales', { headers: headers }),
|
|
27
|
+
axios.get(props.API + '/customers', { headers: headers })
|
|
28
|
+
])
|
|
29
|
+
.then(function(results) {
|
|
30
|
+
setSales(results[0].data);
|
|
31
|
+
setCustomers(results[1].data);
|
|
32
|
+
})
|
|
33
|
+
.catch(function() {});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
useEffect(function() { load(); }, []);
|
|
37
|
+
|
|
38
|
+
function submit() {
|
|
39
|
+
if (!form.invoiceNumber || !form.salesDate || !form.paymentMethod || !form.totalAmountPaid || !form.customer) {
|
|
40
|
+
props.setNotice('All fields are required');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
var payload = {
|
|
44
|
+
invoiceNumber: form.invoiceNumber,
|
|
45
|
+
salesDate: form.salesDate,
|
|
46
|
+
paymentMethod: form.paymentMethod,
|
|
47
|
+
totalAmountPaid: Number(form.totalAmountPaid),
|
|
48
|
+
customer: form.customer
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
var request;
|
|
52
|
+
if (editId) {
|
|
53
|
+
request = axios.put(props.API + '/sales/' + editId, payload, { headers: headers });
|
|
54
|
+
} else {
|
|
55
|
+
request = axios.post(props.API + '/sales', payload, { headers: headers });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
request
|
|
59
|
+
.then(function() {
|
|
60
|
+
setForm(emptySale);
|
|
61
|
+
setEditId('');
|
|
62
|
+
props.setNotice(editId ? 'Sale updated successfully' : 'Sale created successfully');
|
|
63
|
+
return load();
|
|
64
|
+
})
|
|
65
|
+
.catch(function(err) {
|
|
66
|
+
var msg = 'Operation failed';
|
|
67
|
+
if (err.response && err.response.data) {
|
|
68
|
+
msg = err.response.data.message || err.response.data.error || msg;
|
|
69
|
+
}
|
|
70
|
+
props.setNotice(msg);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function edit(sale) {
|
|
75
|
+
setEditId(sale._id);
|
|
76
|
+
setForm({
|
|
77
|
+
invoiceNumber: sale.invoiceNumber,
|
|
78
|
+
salesDate: sale.salesDate ? sale.salesDate.slice(0, 10) : '',
|
|
79
|
+
paymentMethod: sale.paymentMethod,
|
|
80
|
+
totalAmountPaid: String(sale.totalAmountPaid),
|
|
81
|
+
customer: sale.customer ? sale.customer._id : ''
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function remove(id) {
|
|
86
|
+
if (!confirm('Delete this sale?')) return;
|
|
87
|
+
axios.delete(props.API + '/sales/' + id, { headers: headers })
|
|
88
|
+
.then(function() {
|
|
89
|
+
return load();
|
|
90
|
+
})
|
|
91
|
+
.then(function() {
|
|
92
|
+
props.setNotice('Sale deleted successfully');
|
|
93
|
+
})
|
|
94
|
+
.catch(function(err) {
|
|
95
|
+
props.setNotice(err.response && err.response.data ? err.response.data.message : 'Could not delete');
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function dateText(d) {
|
|
100
|
+
return d ? new Date(d).toLocaleDateString() : '-';
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<main className="page">
|
|
105
|
+
<div className="page-title"><h2>Sales</h2><p>{editId ? 'Edit' : 'Add'} sale record.</p></div>
|
|
106
|
+
<section className="form-grid four">
|
|
107
|
+
<input placeholder="Invoice Number" value={form.invoiceNumber} onChange={function(e) { setForm({ invoiceNumber: e.target.value, salesDate: form.salesDate, paymentMethod: form.paymentMethod, totalAmountPaid: form.totalAmountPaid, customer: form.customer }); }} />
|
|
108
|
+
<input type="date" value={form.salesDate} onChange={function(e) { setForm({ invoiceNumber: form.invoiceNumber, salesDate: e.target.value, paymentMethod: form.paymentMethod, totalAmountPaid: form.totalAmountPaid, customer: form.customer }); }} />
|
|
109
|
+
<select value={form.paymentMethod} onChange={function(e) { setForm({ invoiceNumber: form.invoiceNumber, salesDate: form.salesDate, paymentMethod: e.target.value, totalAmountPaid: form.totalAmountPaid, customer: form.customer }); }}>
|
|
110
|
+
<option>Cash</option><option>Credit Card</option><option>Mobile Money</option><option>Bank Transfer</option>
|
|
111
|
+
</select>
|
|
112
|
+
<input type="number" placeholder="Total Amount" value={form.totalAmountPaid} onChange={function(e) { setForm({ invoiceNumber: form.invoiceNumber, salesDate: form.salesDate, paymentMethod: form.paymentMethod, totalAmountPaid: e.target.value, customer: form.customer }); }} />
|
|
113
|
+
<select value={form.customer} onChange={function(e) { setForm({ invoiceNumber: form.invoiceNumber, salesDate: form.salesDate, paymentMethod: form.paymentMethod, totalAmountPaid: form.totalAmountPaid, customer: e.target.value }); }}>
|
|
114
|
+
<option value="">Select Customer</option>
|
|
115
|
+
{customers.map(function(c) { return React.createElement('option', { key: c._id, value: c._id }, c.firstName + ' ' + c.lastName + ' (' + c.customerNumber + ')'); })}
|
|
116
|
+
</select>
|
|
117
|
+
<button onClick={submit}>{editId ? 'Update' : 'Submit Data'}</button>
|
|
118
|
+
{editId ? React.createElement('button', { className: 'danger', onClick: function() { setForm(emptySale); setEditId(''); } }, 'Cancel') : null}
|
|
119
|
+
</section>
|
|
120
|
+
<div className="table-wrap">
|
|
121
|
+
<table>
|
|
122
|
+
<thead>
|
|
123
|
+
<tr>
|
|
124
|
+
<th>Invoice</th><th>Date</th><th>Customer</th><th>Payment</th><th>Amount</th><th>Actions</th>
|
|
125
|
+
</tr>
|
|
126
|
+
</thead>
|
|
127
|
+
<tbody>
|
|
128
|
+
{sales.length === 0 ? (
|
|
129
|
+
<tr><td colSpan="6" style={{ textAlign: 'center', color: '#94a3b8', padding: 20 }}>No sales found</td></tr>
|
|
130
|
+
) : sales.map(function(s) {
|
|
131
|
+
return (
|
|
132
|
+
<tr key={s._id}>
|
|
133
|
+
<td>{s.invoiceNumber}</td>
|
|
134
|
+
<td>{dateText(s.salesDate)}</td>
|
|
135
|
+
<td>{s.customer ? s.customer.firstName + ' ' + s.customer.lastName : 'N/A'}</td>
|
|
136
|
+
<td>{s.paymentMethod}</td>
|
|
137
|
+
<td>{s.totalAmountPaid.toLocaleString()} FRW</td>
|
|
138
|
+
<td>
|
|
139
|
+
<div className="actions">
|
|
140
|
+
<button onClick={function() { edit(s); }}>Edit</button>
|
|
141
|
+
<button className="danger" onClick={function() { remove(s._id); }}>Delete</button>
|
|
142
|
+
</div>
|
|
143
|
+
</td>
|
|
144
|
+
</tr>
|
|
145
|
+
);
|
|
146
|
+
})}
|
|
147
|
+
</tbody>
|
|
148
|
+
</table>
|
|
149
|
+
</div>
|
|
150
|
+
</main>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export default Sales;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { defineConfig } from 'vite'
|
|
2
2
|
import react from '@vitejs/plugin-react'
|
|
3
|
-
|
|
4
|
-
// https://vite.dev/config/
|
|
3
|
+
|
|
5
4
|
export default defineConfig({
|
|
6
|
-
plugins: [react()
|
|
5
|
+
plugins: [react()],
|
|
6
|
+
server: {
|
|
7
|
+
port: 5173,
|
|
8
|
+
},
|
|
7
9
|
})
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
const mongoose = require('mongoose');
|
|
2
|
-
|
|
3
|
-
const connectDB = async () => {
|
|
4
|
-
try {
|
|
5
|
-
await mongoose.connect('mongodb://localhost:27017/SCMS');
|
|
6
|
-
console.log('MongoDB connected');
|
|
7
|
-
} catch (error) {
|
|
8
|
-
console.error('MongoDB connection error:', error);
|
|
9
|
-
}
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
module.exports = connectDB;
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
const bcrypt = require('bcrypt');
|
|
2
|
-
const jwt = require('jsonwebtoken');
|
|
3
|
-
const User = require('../models/User');
|
|
4
|
-
const JWT_SECRET = 'change_this_to_a_long_random_secret';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
function createToken(userId) {
|
|
9
|
-
return jwt.sign({ userId },JWT_SECRET, { expiresIn: '7d' });
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function formatUser(user) {
|
|
13
|
-
return {
|
|
14
|
-
id: user._id,
|
|
15
|
-
name: user.name,
|
|
16
|
-
email: user.email,
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
exports.register = async (req, res) => {
|
|
21
|
-
try {
|
|
22
|
-
const { name, email, password } = req.body;
|
|
23
|
-
|
|
24
|
-
if (!name || !email || !password) {
|
|
25
|
-
return res.status(400).json({ message: 'Name, email, and password are required' });
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (password.length < 6) {
|
|
29
|
-
return res.status(400).json({ message: 'Password must be at least 6 characters' });
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const existing = await User.findOne({ email: email.toLowerCase() });
|
|
33
|
-
if (existing) {
|
|
34
|
-
return res.status(409).json({ message: 'Email already registered' });
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const hashedPassword = await bcrypt.hash(password, 10);
|
|
38
|
-
const user = await User.create({
|
|
39
|
-
name,
|
|
40
|
-
email: email.toLowerCase(),//to ensure the email is always lowercase
|
|
41
|
-
password: hashedPassword,
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
const token = createToken(user._id);
|
|
45
|
-
|
|
46
|
-
res.status(201).json({
|
|
47
|
-
token,
|
|
48
|
-
user: formatUser(user),
|
|
49
|
-
});
|
|
50
|
-
} catch (err) {
|
|
51
|
-
res.status(500).json({ message: err.message });
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
exports.login = async (req, res) => {
|
|
56
|
-
try {
|
|
57
|
-
const { email, password } = req.body;
|
|
58
|
-
|
|
59
|
-
if (!email || !password) {
|
|
60
|
-
return res.status(400).json({ message: 'Email and password are required' });
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const user = await User.findOne({ email: email.toLowerCase() });
|
|
64
|
-
if (!user) {
|
|
65
|
-
return res.status(401).json({ message: 'Invalid email or password' });
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const match = await bcrypt.compare(password, user.password);
|
|
69
|
-
if (!match) {
|
|
70
|
-
return res.status(401).json({ message: 'Invalid email or password' });
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const token = createToken(user._id);
|
|
74
|
-
|
|
75
|
-
res.json({
|
|
76
|
-
token,
|
|
77
|
-
user: formatUser(user),
|
|
78
|
-
});
|
|
79
|
-
} catch (err) {
|
|
80
|
-
res.status(500).json({ message: err.message });
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
exports.getMe = async (req, res) => {
|
|
85
|
-
try {
|
|
86
|
-
res.json({ user: formatUser(req.user) });
|
|
87
|
-
} catch (err) {
|
|
88
|
-
res.status(500).json({ message: err.message });
|
|
89
|
-
}
|
|
90
|
-
};
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
const Delivery = require('../models/delivery');
|
|
2
|
-
const Shipment = require('../models/shipment');
|
|
3
|
-
|
|
4
|
-
exports.addDelivery = async (req, res) => {
|
|
5
|
-
try {
|
|
6
|
-
const { deliveryCode, deliveryDate, quantityDelivered, deliveryStatus, shipmentId } = req.body;
|
|
7
|
-
|
|
8
|
-
if (shipmentId) {
|
|
9
|
-
const shipment = await Shipment.findById(shipmentId);
|
|
10
|
-
if (!shipment) return res.status(404).json({ msg: 'Shipment not found' });
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const newDelivery = await Delivery.create({
|
|
14
|
-
deliveryCode,
|
|
15
|
-
deliveryDate,
|
|
16
|
-
quantityDelivered,
|
|
17
|
-
deliveryStatus,
|
|
18
|
-
shipment: shipmentId || null,
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
res.status(201).json(newDelivery);
|
|
22
|
-
} catch (error) {
|
|
23
|
-
res.status(500).json({ msg: 'Failed to add delivery', error: error.message });
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
exports.getDeliveries = async (req, res) => {
|
|
28
|
-
try {
|
|
29
|
-
const deliveries = await Delivery.find().populate({ path: 'shipment', populate: 'supplier' });
|
|
30
|
-
res.status(200).json(deliveries);
|
|
31
|
-
} catch (error) {
|
|
32
|
-
res.status(500).json({ msg: 'Failed to fetch deliveries', error: error.message });
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
exports.getDeliveryById = async (req, res) => {
|
|
37
|
-
try {
|
|
38
|
-
const delivery = await Delivery.findById(req.params.id).populate({ path: 'shipment', populate: 'supplier' });
|
|
39
|
-
if (!delivery) return res.status(404).json({ msg: 'Delivery not found' });
|
|
40
|
-
res.status(200).json(delivery);
|
|
41
|
-
} catch (error) {
|
|
42
|
-
res.status(500).json({ msg: 'Failed to fetch delivery', error: error.message });
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
exports.updateDelivery = async (req, res) => {
|
|
47
|
-
try {
|
|
48
|
-
const { shipmentId } = req.body;
|
|
49
|
-
|
|
50
|
-
if (shipmentId) {
|
|
51
|
-
const shipment = await Shipment.findById(shipmentId);
|
|
52
|
-
if (!shipment) return res.status(404).json({ msg: 'Shipment not found' });
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const updatedDelivery = await Delivery.findByIdAndUpdate(
|
|
56
|
-
req.params.id,
|
|
57
|
-
{
|
|
58
|
-
...req.body,
|
|
59
|
-
shipment: shipmentId || null,
|
|
60
|
-
},
|
|
61
|
-
{ new: true }
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
if (!updatedDelivery) return res.status(404).json({ msg: 'Delivery not found' });
|
|
65
|
-
res.status(200).json(updatedDelivery);
|
|
66
|
-
} catch (error) {
|
|
67
|
-
res.status(500).json({ msg: 'Failed to update delivery', error: error.message });
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
exports.deleteDelivery = async (req, res) => {
|
|
72
|
-
try {
|
|
73
|
-
const deletedDelivery = await Delivery.findByIdAndDelete(req.params.id);
|
|
74
|
-
if (!deletedDelivery) return res.status(404).json({ msg: 'Delivery not found' });
|
|
75
|
-
res.status(200).json({ msg: 'Delivery deleted successfully' });
|
|
76
|
-
} catch (error) {
|
|
77
|
-
res.status(500).json({ msg: 'Failed to delete delivery', error: error.message });
|
|
78
|
-
}
|
|
79
|
-
};
|