├── Backend ├── .gitignore ├── controller │ ├── product.js │ ├── purchase.js │ ├── purchaseStock.js │ ├── sales.js │ ├── soldStock.js │ └── store.js ├── models │ ├── index.js │ ├── product.js │ ├── purchase.js │ ├── sales.js │ ├── store.js │ └── users.js ├── package-lock.json ├── package.json ├── router │ ├── product.js │ ├── purchase.js │ ├── sales.js │ └── store.js └── server.js ├── Frontend ├── .gitignore ├── README.md ├── README.md~ ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── AuthContext.js │ ├── ProtectedWrapper.js │ ├── assets │ │ ├── 20943629.eps │ │ ├── License free.txt │ │ ├── License premium.txt │ │ ├── Login.png │ │ ├── add-product.png │ │ ├── dashboard-icon.png │ │ ├── download.png │ │ ├── filter-icon.png │ │ ├── inventory-icon.png │ │ ├── location-icon.png │ │ ├── logo.png │ │ ├── mi-logo (2).jpg │ │ ├── mi-logo.png │ │ ├── order-icon.png │ │ ├── reports-icon.png │ │ ├── search-icon.png │ │ ├── signup-img.zip │ │ ├── signup.jpg │ │ ├── store-image.jpg │ │ └── supplier-icon.png │ ├── components │ │ ├── AddProduct.js │ │ ├── AddPurchaseDetails.js │ │ ├── AddSale.js │ │ ├── AddStore.js │ │ ├── Header.js │ │ ├── Layout.js │ │ ├── SideMenu.js │ │ ├── UpdateProduct.js │ │ └── UploadImage.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── pages │ │ ├── Dashboard.js │ │ ├── Inventory.js │ │ ├── Login.js │ │ ├── NoPageFound.js │ │ ├── PurchaseDetails.js │ │ ├── Register.js │ │ ├── Sales.js │ │ └── Store.js │ ├── reportWebVitals.js │ └── setupTests.js └── tailwind.config.js └── README.md /Backend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* -------------------------------------------------------------------------------- /Backend/controller/product.js: -------------------------------------------------------------------------------- 1 | const Product = require("../models/Product"); 2 | const Purchase = require("../models/purchase"); 3 | const Sales = require("../models/sales"); 4 | 5 | // Add Post 6 | const addProduct = (req, res) => { 7 | console.log("req: ", req.body.userId); 8 | const addProduct = new Product({ 9 | userID: req.body.userId, 10 | name: req.body.name, 11 | manufacturer: req.body.manufacturer, 12 | stock: 0, 13 | description: req.body.description, 14 | }); 15 | 16 | addProduct 17 | .save() 18 | .then((result) => { 19 | res.status(200).send(result); 20 | }) 21 | .catch((err) => { 22 | res.status(402).send(err); 23 | }); 24 | }; 25 | 26 | // Get All Products 27 | const getAllProducts = async (req, res) => { 28 | const findAllProducts = await Product.find({ 29 | userID: req.params.userId, 30 | }).sort({ _id: -1 }); // -1 for descending; 31 | res.json(findAllProducts); 32 | }; 33 | 34 | // Delete Selected Product 35 | const deleteSelectedProduct = async (req, res) => { 36 | const deleteProduct = await Product.deleteOne( 37 | { _id: req.params.id } 38 | ); 39 | const deletePurchaseProduct = await Purchase.deleteOne( 40 | { ProductID: req.params.id } 41 | ); 42 | 43 | const deleteSaleProduct = await Sales.deleteOne( 44 | { ProductID: req.params.id } 45 | ); 46 | res.json({ deleteProduct, deletePurchaseProduct, deleteSaleProduct }); 47 | }; 48 | 49 | // Update Selected Product 50 | const updateSelectedProduct = async (req, res) => { 51 | try { 52 | const updatedResult = await Product.findByIdAndUpdate( 53 | { _id: req.body.productID }, 54 | { 55 | name: req.body.name, 56 | manufacturer: req.body.manufacturer, 57 | description: req.body.description, 58 | }, 59 | { new: true } 60 | ); 61 | console.log(updatedResult); 62 | res.json(updatedResult); 63 | } catch (error) { 64 | console.log(error); 65 | res.status(402).send("Error"); 66 | } 67 | }; 68 | 69 | // Search Products 70 | const searchProduct = async (req, res) => { 71 | const searchTerm = req.query.searchTerm; 72 | const products = await Product.find({ 73 | name: { $regex: searchTerm, $options: "i" }, 74 | }); 75 | res.json(products); 76 | }; 77 | 78 | module.exports = { 79 | addProduct, 80 | getAllProducts, 81 | deleteSelectedProduct, 82 | updateSelectedProduct, 83 | searchProduct, 84 | }; 85 | -------------------------------------------------------------------------------- /Backend/controller/purchase.js: -------------------------------------------------------------------------------- 1 | const Purchase = require("../models/purchase"); 2 | const purchaseStock = require("./purchaseStock"); 3 | 4 | // Add Purchase Details 5 | const addPurchase = (req, res) => { 6 | const addPurchaseDetails = new Purchase({ 7 | userID: req.body.userID, 8 | ProductID: req.body.productID, 9 | QuantityPurchased: req.body.quantityPurchased, 10 | PurchaseDate: req.body.purchaseDate, 11 | TotalPurchaseAmount: req.body.totalPurchaseAmount, 12 | }); 13 | 14 | addPurchaseDetails 15 | .save() 16 | .then((result) => { 17 | purchaseStock(req.body.productID, req.body.quantityPurchased); 18 | res.status(200).send(result); 19 | }) 20 | .catch((err) => { 21 | res.status(402).send(err); 22 | }); 23 | }; 24 | 25 | // Get All Purchase Data 26 | const getPurchaseData = async (req, res) => { 27 | const findAllPurchaseData = await Purchase.find({"userID": req.params.userID}) 28 | .sort({ _id: -1 }) 29 | .populate("ProductID"); // -1 for descending order 30 | res.json(findAllPurchaseData); 31 | }; 32 | 33 | // Get total purchase amount 34 | const getTotalPurchaseAmount = async (req, res) => { 35 | let totalPurchaseAmount = 0; 36 | const purchaseData = await Purchase.find({"userID": req.params.userID}); 37 | purchaseData.forEach((purchase) => { 38 | totalPurchaseAmount += purchase.TotalPurchaseAmount; 39 | }); 40 | res.json({ totalPurchaseAmount }); 41 | }; 42 | 43 | module.exports = { addPurchase, getPurchaseData, getTotalPurchaseAmount }; 44 | -------------------------------------------------------------------------------- /Backend/controller/purchaseStock.js: -------------------------------------------------------------------------------- 1 | const Purchase = require("../models/purchase"); 2 | const Product = require("../models/Product"); 3 | 4 | const purchaseStock = async (productID, purchaseStockData) => { 5 | // Updating Purchase stock 6 | try { 7 | const myProductData = await Product.findOne({ _id: productID }); 8 | let myUpdatedStock = parseInt(myProductData.stock) + purchaseStockData; 9 | 10 | const PurchaseStock = await Product.findByIdAndUpdate( 11 | { _id: productID }, 12 | { 13 | stock: myUpdatedStock, 14 | }, 15 | { new: true } 16 | ); 17 | console.log(PurchaseStock); 18 | } catch (error) { 19 | console.error("Error updating Purchase stock ", error); 20 | } 21 | }; 22 | 23 | module.exports = purchaseStock; 24 | -------------------------------------------------------------------------------- /Backend/controller/sales.js: -------------------------------------------------------------------------------- 1 | const Sales = require("../models/sales"); 2 | const soldStock = require("../controller/soldStock"); 3 | 4 | // Add Sales 5 | const addSales = (req, res) => { 6 | const addSale = new Sales({ 7 | userID: req.body.userID, 8 | ProductID: req.body.productID, 9 | StoreID: req.body.storeID, 10 | StockSold: req.body.stockSold, 11 | SaleDate: req.body.saleDate, 12 | TotalSaleAmount: req.body.totalSaleAmount, 13 | }); 14 | 15 | addSale 16 | .save() 17 | .then((result) => { 18 | soldStock(req.body.productID, req.body.stockSold); 19 | res.status(200).send(result); 20 | }) 21 | .catch((err) => { 22 | res.status(402).send(err); 23 | }); 24 | }; 25 | 26 | // Get All Sales Data 27 | const getSalesData = async (req, res) => { 28 | const findAllSalesData = await Sales.find({"userID": req.params.userID}) 29 | .sort({ _id: -1 }) 30 | .populate("ProductID") 31 | .populate("StoreID"); // -1 for descending order 32 | res.json(findAllSalesData); 33 | }; 34 | 35 | // Get total sales amount 36 | const getTotalSalesAmount = async(req,res) => { 37 | let totalSaleAmount = 0; 38 | const salesData = await Sales.find({"userID": req.params.userID}); 39 | salesData.forEach((sale)=>{ 40 | totalSaleAmount += sale.TotalSaleAmount; 41 | }) 42 | res.json({totalSaleAmount}); 43 | 44 | } 45 | 46 | const getMonthlySales = async (req, res) => { 47 | try { 48 | const sales = await Sales.find(); 49 | 50 | // Initialize array with 12 zeros 51 | const salesAmount = []; 52 | salesAmount.length = 12; 53 | salesAmount.fill(0) 54 | 55 | sales.forEach((sale) => { 56 | const monthIndex = parseInt(sale.SaleDate.split("-")[1]) - 1; 57 | 58 | salesAmount[monthIndex] += sale.TotalSaleAmount; 59 | }); 60 | 61 | res.status(200).json({ salesAmount }); 62 | } catch (err) { 63 | console.error(err); 64 | res.status(500).json({ error: "Server error" }); 65 | } 66 | }; 67 | 68 | 69 | 70 | module.exports = { addSales, getMonthlySales, getSalesData, getTotalSalesAmount}; 71 | -------------------------------------------------------------------------------- /Backend/controller/soldStock.js: -------------------------------------------------------------------------------- 1 | const Sales = require("../models/sales"); 2 | const Product = require("../models/Product"); 3 | 4 | 5 | const soldStock = async (productID, stockSoldData) => { 6 | 7 | // Updating sold stock 8 | try { 9 | 10 | const myProductData = await Product.findOne({ _id: productID }); 11 | let myUpdatedStock = myProductData.stock - stockSoldData; 12 | console.log("MY SOLD STOCK: ", myUpdatedStock); 13 | 14 | const SoldStock = await Product.findByIdAndUpdate( 15 | { _id: productID }, 16 | { 17 | stock: myUpdatedStock, 18 | }, 19 | { new: true } 20 | ); 21 | console.log(SoldStock); 22 | 23 | } catch (error) { 24 | console.error("Error updating sold stock ", error); 25 | } 26 | }; 27 | 28 | module.exports = soldStock; 29 | -------------------------------------------------------------------------------- /Backend/controller/store.js: -------------------------------------------------------------------------------- 1 | const Store = require("../models/store"); 2 | 3 | // Add Store 4 | const addStore = async (req, res) => { 5 | console.log(req.body) 6 | const addStore = await new Store({ 7 | userID : req.body.userId, 8 | name: req.body.name, 9 | category: req.body.category, 10 | address: req.body.address, 11 | city: req.body.city, 12 | image: req.body.image 13 | }); 14 | 15 | addStore.save().then((result) => { 16 | res.status(200).send(result); 17 | }) 18 | .catch((err) => { 19 | res.status(402).send(err); 20 | }); 21 | }; 22 | 23 | // Get All Stores 24 | const getAllStores = async (req, res) => { 25 | const findAllStores = await Store.find({"userID": req.params.userID}).sort({ _id: -1 }); // -1 for descending; 26 | res.json(findAllStores); 27 | }; 28 | 29 | module.exports = { addStore, getAllStores }; 30 | -------------------------------------------------------------------------------- /Backend/models/index.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const uri = "mongodb+srv://adminhamza:adminhamza123&@cluster0.pzcviot.mongodb.net/InventoryManagementApp?retryWrites=true&w=majority"; 3 | 4 | 5 | function main() { 6 | mongoose.connect(uri).then(() => { 7 | console.log("Succesfull") 8 | 9 | }).catch((err) => { 10 | console.log("Error: ", err) 11 | }) 12 | } 13 | 14 | module.exports = { main }; -------------------------------------------------------------------------------- /Backend/models/product.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const ProductSchema = new mongoose.Schema( 4 | { 5 | userID: { 6 | type: mongoose.Schema.Types.ObjectId, 7 | ref: 'users', 8 | required: true, 9 | }, 10 | name: { 11 | type: String, 12 | required: true, 13 | }, 14 | manufacturer: { 15 | type: String, 16 | required: true, 17 | }, 18 | stock: { 19 | type: Number, 20 | required: true, 21 | }, 22 | description: String, 23 | }, 24 | { timestamps: true } 25 | ); 26 | 27 | 28 | const Product = mongoose.model("product", ProductSchema); 29 | module.exports = Product; 30 | -------------------------------------------------------------------------------- /Backend/models/purchase.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const PurchaseSchema = new mongoose.Schema( 4 | { 5 | userID: { 6 | type: mongoose.Schema.Types.ObjectId, 7 | ref: "users", 8 | required: true, 9 | }, 10 | ProductID: { 11 | type: mongoose.Schema.Types.ObjectId, 12 | ref: "product", 13 | required: true, 14 | }, 15 | QuantityPurchased: { 16 | type: Number, 17 | required: true, 18 | }, 19 | PurchaseDate: { 20 | type: String, 21 | required: true, 22 | }, 23 | TotalPurchaseAmount: { 24 | type: Number, 25 | required: true, 26 | }, 27 | }, 28 | { timestamps: true } 29 | ); 30 | 31 | const Purchase = mongoose.model("purchase", PurchaseSchema); 32 | module.exports = Purchase; 33 | -------------------------------------------------------------------------------- /Backend/models/sales.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const SaleSchema = new mongoose.Schema( 4 | { 5 | userID: { 6 | type: mongoose.Schema.Types.ObjectId, 7 | ref: "users", 8 | required: true, 9 | }, 10 | ProductID: { 11 | type: mongoose.Schema.Types.ObjectId, 12 | ref: "product", 13 | required: true, 14 | }, 15 | StoreID: { 16 | type: mongoose.Schema.Types.ObjectId, 17 | ref: "store", 18 | required: true, 19 | }, 20 | StockSold: { 21 | type: Number, 22 | required: true, 23 | }, 24 | SaleDate: { 25 | type: String, 26 | required: true, 27 | }, 28 | TotalSaleAmount: { 29 | type: Number, 30 | required: true, 31 | }, 32 | }, 33 | { timestamps: true } 34 | ); 35 | 36 | const Sales = mongoose.model("sales", SaleSchema); 37 | module.exports = Sales; 38 | -------------------------------------------------------------------------------- /Backend/models/store.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | const StoreSchema = new mongoose.Schema( 4 | { 5 | userID: { 6 | type: mongoose.Schema.Types.ObjectId, 7 | ref: 'users', 8 | required: true, 9 | }, 10 | name: { 11 | type: String, 12 | required: true, 13 | }, 14 | category: { 15 | type: String, 16 | required: true, 17 | }, 18 | address: { 19 | type: String, 20 | required: true, 21 | }, 22 | city: { 23 | type: String, 24 | required: true, 25 | }, 26 | image: { 27 | type: String, 28 | required: true, 29 | }, 30 | }, 31 | { timestamps: true } 32 | ); 33 | 34 | const Store = mongoose.model("store", StoreSchema); 35 | module.exports = Store; 36 | -------------------------------------------------------------------------------- /Backend/models/users.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const UserSchema = new mongoose.Schema({ 4 | firstName: 'String', 5 | lastName : 'String', 6 | email: 'String', 7 | password: 'String', 8 | phoneNumber: 'Number', 9 | imageUrl: 'String', 10 | }); 11 | 12 | const User = mongoose.model("users", UserSchema); 13 | module.exports = User; -------------------------------------------------------------------------------- /Backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "serverStart": "nodemon server.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "cors": "^2.8.5", 14 | "express": "^4.18.2", 15 | "mongoose": "^7.0.2", 16 | "multer": "^1.4.5-lts.1", 17 | "nodemon": "^2.0.21" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Backend/router/product.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | const product = require("../controller/product"); 4 | 5 | // Add Product 6 | app.post("/add", product.addProduct); 7 | 8 | // Get All Products 9 | app.get("/get/:userId", product.getAllProducts); 10 | 11 | // Delete Selected Product Item 12 | app.get("/delete/:id", product.deleteSelectedProduct); 13 | 14 | // Update Selected Product 15 | app.post("/update", product.updateSelectedProduct); 16 | 17 | // Search Product 18 | app.get("/search", product.searchProduct); 19 | 20 | // http://localhost:4000/api/product/search?searchTerm=fa 21 | 22 | module.exports = app; 23 | -------------------------------------------------------------------------------- /Backend/router/purchase.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | const purchase = require("../controller/purchase"); 4 | 5 | // Add Purchase 6 | app.post("/add", purchase.addPurchase); 7 | 8 | // Get All Purchase Data 9 | app.get("/get/:userID", purchase.getPurchaseData); 10 | 11 | app.get("/get/:userID/totalpurchaseamount", purchase.getTotalPurchaseAmount); 12 | 13 | module.exports = app; 14 | 15 | // http://localhost:4000/api/purchase/add POST 16 | // http://localhost:4000/api/purchase/get GET 17 | -------------------------------------------------------------------------------- /Backend/router/sales.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | const sales = require("../controller/sales"); 4 | 5 | // Add Sales 6 | app.post("/add", sales.addSales); 7 | 8 | // Get All Sales 9 | app.get("/get/:userID", sales.getSalesData); 10 | app.get("/getmonthly", sales.getMonthlySales); 11 | 12 | 13 | app.get("/get/:userID/totalsaleamount", sales.getTotalSalesAmount); 14 | 15 | module.exports = app; 16 | 17 | 18 | 19 | // http://localhost:4000/api/sales/add POST 20 | // http://localhost:4000/api/sales/get GET 21 | -------------------------------------------------------------------------------- /Backend/router/store.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | const store = require("../controller/store"); 4 | 5 | // Add Store 6 | app.post("/add", store.addStore); 7 | 8 | // Get All Store 9 | app.get("/get/:userID", store.getAllStores) 10 | 11 | module.exports = app; 12 | -------------------------------------------------------------------------------- /Backend/server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const { main } = require("./models/index"); 3 | const productRoute = require("./router/product"); 4 | const storeRoute = require("./router/store"); 5 | const purchaseRoute = require("./router/purchase"); 6 | const salesRoute = require("./router/sales"); 7 | const cors = require("cors"); 8 | const User = require("./models/users"); 9 | const Product = require("./models/Product"); 10 | 11 | 12 | const app = express(); 13 | const PORT = 4000; 14 | main(); 15 | app.use(express.json()); 16 | app.use(cors()); 17 | 18 | // Store API 19 | app.use("/api/store", storeRoute); 20 | 21 | // Products API 22 | app.use("/api/product", productRoute); 23 | 24 | // Purchase API 25 | app.use("/api/purchase", purchaseRoute); 26 | 27 | // Sales API 28 | app.use("/api/sales", salesRoute); 29 | 30 | // ------------- Signin -------------- 31 | let userAuthCheck; 32 | app.post("/api/login", async (req, res) => { 33 | console.log(req.body); 34 | // res.send("hi"); 35 | try { 36 | const user = await User.findOne({ 37 | email: req.body.email, 38 | password: req.body.password, 39 | }); 40 | console.log("USER: ", user); 41 | if (user) { 42 | res.send(user); 43 | userAuthCheck = user; 44 | } else { 45 | res.status(401).send("Invalid Credentials"); 46 | userAuthCheck = null; 47 | } 48 | } catch (error) { 49 | console.log(error); 50 | res.send(error); 51 | } 52 | }); 53 | 54 | // Getting User Details of login user 55 | app.get("/api/login", (req, res) => { 56 | res.send(userAuthCheck); 57 | }); 58 | // ------------------------------------ 59 | 60 | // Registration API 61 | app.post("/api/register", (req, res) => { 62 | let registerUser = new User({ 63 | firstName: req.body.firstName, 64 | lastName: req.body.lastName, 65 | email: req.body.email, 66 | password: req.body.password, 67 | phoneNumber: req.body.phoneNumber, 68 | imageUrl: req.body.imageUrl, 69 | }); 70 | 71 | registerUser 72 | .save() 73 | .then((result) => { 74 | res.status(200).send(result); 75 | alert("Signup Successfull"); 76 | }) 77 | .catch((err) => console.log("Signup: ", err)); 78 | console.log("request: ", req.body); 79 | }); 80 | 81 | 82 | app.get("/testget", async (req,res)=>{ 83 | const result = await Product.findOne({ _id: '6429979b2e5434138eda1564'}) 84 | res.json(result) 85 | 86 | }) 87 | 88 | // Here we are listening to the server 89 | app.listen(PORT, () => { 90 | console.log("I am live again"); 91 | }); 92 | -------------------------------------------------------------------------------- /Frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Frontend/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `npm start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 13 | 14 | The page will reload when you make changes.\ 15 | You may also see any lint errors in the console. 16 | 17 | ### `npm test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `npm run eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!** 35 | 36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. 39 | 40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `npm run build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | # React-Inventory-Management-System 72 | -------------------------------------------------------------------------------- /Frontend/README.md~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/README.md~ -------------------------------------------------------------------------------- /Frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "inventory-management-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@headlessui/react": "^1.7.13", 7 | "@heroicons/react": "^2.0.16", 8 | "@tailwindcss/forms": "^0.5.3", 9 | "@testing-library/jest-dom": "^5.16.5", 10 | "@testing-library/react": "^13.4.0", 11 | "@testing-library/user-event": "^13.5.0", 12 | "apexcharts": "^3.37.2", 13 | "chart.js": "^4.2.1", 14 | "react": "^18.2.0", 15 | "react-apexcharts": "^1.4.0", 16 | "react-chartjs-2": "^5.2.0", 17 | "react-dom": "^18.2.0", 18 | "react-router-dom": "^6.9.0", 19 | "react-scripts": "5.0.1", 20 | "web-vitals": "^2.1.4" 21 | }, 22 | "scripts": { 23 | "start": "react-scripts start", 24 | "build": "react-scripts build", 25 | "test": "react-scripts test", 26 | "eject": "react-scripts eject" 27 | }, 28 | "eslintConfig": { 29 | "extends": [ 30 | "react-app", 31 | "react-app/jest" 32 | ] 33 | }, 34 | "browserslist": { 35 | "production": [ 36 | ">0.2%", 37 | "not dead", 38 | "not op_mini all" 39 | ], 40 | "development": [ 41 | "last 1 chrome version", 42 | "last 1 firefox version", 43 | "last 1 safari version" 44 | ] 45 | }, 46 | "devDependencies": { 47 | "tailwindcss": "^3.2.7" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/public/favicon.ico -------------------------------------------------------------------------------- /Frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Frontend/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/public/logo192.png -------------------------------------------------------------------------------- /Frontend/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/public/logo512.png -------------------------------------------------------------------------------- /Frontend/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /Frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Frontend/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Frontend/src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Login from "./pages/Login"; 3 | import Register from "./pages/Register"; 4 | import Dashboard from "./pages/Dashboard"; 5 | import "./index.css"; 6 | import { BrowserRouter, Routes, Route } from "react-router-dom"; 7 | import Layout from "./components/Layout"; 8 | import Inventory from "./pages/Inventory"; 9 | import NoPageFound from "./pages/NoPageFound"; 10 | import AuthContext from "./AuthContext"; 11 | import ProtectedWrapper from "./ProtectedWrapper"; 12 | import { useEffect, useState } from "react"; 13 | import Store from "./pages/Store"; 14 | import Sales from "./pages/Sales"; 15 | import PurchaseDetails from "./pages/PurchaseDetails"; 16 | 17 | const App = () => { 18 | const [user, setUser] = useState(""); 19 | const [loader, setLoader] = useState(true); 20 | let myLoginUser = JSON.parse(localStorage.getItem("user")); 21 | // console.log("USER: ",user) 22 | 23 | useEffect(() => { 24 | if (myLoginUser) { 25 | setUser(myLoginUser._id); 26 | setLoader(false); 27 | // console.log("inside effect", myLoginUser) 28 | } else { 29 | setUser(""); 30 | setLoader(false); 31 | } 32 | }, [myLoginUser]); 33 | 34 | const signin = (newUser, callback) => { 35 | setUser(newUser); 36 | callback(); 37 | }; 38 | 39 | const signout = () => { 40 | setUser(null); 41 | localStorage.removeItem("user"); 42 | }; 43 | 44 | let value = { user, signin, signout }; 45 | 46 | if (loader) 47 | return ( 48 |
56 |

LOADING...

57 |
58 | ); 59 | 60 | return ( 61 | 62 | 63 | 64 | } /> 65 | } /> 66 | 70 | 71 | 72 | } 73 | > 74 | } /> 75 | } /> 76 | } /> 77 | } /> 78 | } /> 79 | 80 | } /> 81 | 82 | 83 | 84 | ); 85 | }; 86 | 87 | export default App; 88 | -------------------------------------------------------------------------------- /Frontend/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /Frontend/src/AuthContext.js: -------------------------------------------------------------------------------- 1 | import { createContext } from "react"; 2 | 3 | let AuthContext = createContext(null); 4 | 5 | export default AuthContext; 6 | -------------------------------------------------------------------------------- /Frontend/src/ProtectedWrapper.js: -------------------------------------------------------------------------------- 1 | import AuthContext from "./AuthContext"; 2 | import { useContext } from "react"; 3 | import { Navigate } from "react-router-dom"; 4 | 5 | function ProtectedWrapper(props) { 6 | const auth = useContext(AuthContext); 7 | // console.log("===================================="); 8 | // console.log(auth); 9 | // console.log("===================================="); 10 | 11 | if (!auth.user) { 12 | return ; 13 | } 14 | 15 | return props.children; 16 | } 17 | export default ProtectedWrapper; 18 | -------------------------------------------------------------------------------- /Frontend/src/assets/20943629.eps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/20943629.eps -------------------------------------------------------------------------------- /Frontend/src/assets/License free.txt: -------------------------------------------------------------------------------- 1 | IMPORTANT NOTICE: This license only applies if you downloaded this content as 2 | an unsubscribed user. If you are a premium user (ie, you pay a subscription) 3 | you are bound to the license terms described in the accompanying file 4 | "License premium.txt". 5 | 6 | --------------------- 7 | 8 | You must attribute the image to its author: 9 | 10 | In order to use a content or a part of it, you must attribute it to vectorjuice / Freepik, 11 | so we will be able to continue creating new graphic resources every day. 12 | 13 | 14 | How to attribute it? 15 | 16 | For websites: 17 | 18 | Please, copy this code on your website to accredit the author: 19 | Designed by vectorjuice / Freepik 20 | 21 | For printing: 22 | 23 | Paste this text on the final work so the authorship is known. 24 | - For example, in the acknowledgements chapter of a book: 25 | "Designed by vectorjuice / Freepik" 26 | 27 | 28 | You are free to use this image: 29 | 30 | - For both personal and commercial projects and to modify it. 31 | - In a website or presentation template or application or as part of your design. 32 | 33 | You are not allowed to: 34 | 35 | - Sub-license, resell or rent it. 36 | - Include it in any online or offline archive or database. 37 | 38 | The full terms of the license are described in section 7 of the Freepik 39 | terms of use, available online in the following link: 40 | 41 | http://www.freepik.com/terms_of_use 42 | 43 | The terms described in the above link have precedence over the terms described 44 | in the present document. In case of disagreement, the Freepik Terms of Use 45 | will prevail. 46 | -------------------------------------------------------------------------------- /Frontend/src/assets/License premium.txt: -------------------------------------------------------------------------------- 1 | IMPORTANT NOTICE: This license only applies if you downloaded this content as 2 | a subscribed (or "premium") user. If you are an unsubscribed user (or "free" 3 | user) you are bound to the license terms described in the accompanying file 4 | "License free.txt". 5 | 6 | --------------------- 7 | 8 | You can download from your profile in Freepik a personalized license stating 9 | your right to use this content as a "premium" user: 10 | 11 | https://profile.freepik.com/my_downloads 12 | 13 | You are free to use this image: 14 | 15 | - For both personal and commercial projects and to modify it. 16 | - In a website or presentation template or application or as part of your design. 17 | 18 | You are not allowed to: 19 | 20 | - Sub-license, resell or rent it. 21 | - Include it in any online or offline archive or database. 22 | 23 | The full terms of the license are described in sections 7 and 8 of the Freepik 24 | terms of use, available online in the following link: 25 | 26 | http://www.freepik.com/terms_of_use 27 | 28 | The terms described in the above link have precedence over the terms described 29 | in the present document. In case of disagreement, the Freepik Terms of Use 30 | will prevail. 31 | -------------------------------------------------------------------------------- /Frontend/src/assets/Login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/Login.png -------------------------------------------------------------------------------- /Frontend/src/assets/add-product.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/add-product.png -------------------------------------------------------------------------------- /Frontend/src/assets/dashboard-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/dashboard-icon.png -------------------------------------------------------------------------------- /Frontend/src/assets/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/download.png -------------------------------------------------------------------------------- /Frontend/src/assets/filter-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/filter-icon.png -------------------------------------------------------------------------------- /Frontend/src/assets/inventory-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/inventory-icon.png -------------------------------------------------------------------------------- /Frontend/src/assets/location-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/location-icon.png -------------------------------------------------------------------------------- /Frontend/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/logo.png -------------------------------------------------------------------------------- /Frontend/src/assets/mi-logo (2).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/mi-logo (2).jpg -------------------------------------------------------------------------------- /Frontend/src/assets/mi-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/mi-logo.png -------------------------------------------------------------------------------- /Frontend/src/assets/order-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/order-icon.png -------------------------------------------------------------------------------- /Frontend/src/assets/reports-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/reports-icon.png -------------------------------------------------------------------------------- /Frontend/src/assets/search-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/search-icon.png -------------------------------------------------------------------------------- /Frontend/src/assets/signup-img.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/signup-img.zip -------------------------------------------------------------------------------- /Frontend/src/assets/signup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/signup.jpg -------------------------------------------------------------------------------- /Frontend/src/assets/store-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/store-image.jpg -------------------------------------------------------------------------------- /Frontend/src/assets/supplier-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhamzashaikh/React-Inventory-Management-System/6bfe18edb0fc097653ca0b45d7a9d6ebd0bdac56/Frontend/src/assets/supplier-icon.png -------------------------------------------------------------------------------- /Frontend/src/components/AddProduct.js: -------------------------------------------------------------------------------- 1 | import { Fragment, useContext, useRef, useState } from "react"; 2 | import { Dialog, Transition } from "@headlessui/react"; 3 | import { PlusIcon } from "@heroicons/react/24/outline"; 4 | import AuthContext from "../AuthContext"; 5 | 6 | export default function AddProduct({ 7 | addProductModalSetting, 8 | handlePageUpdate, 9 | }) { 10 | const authContext = useContext(AuthContext); 11 | const [product, setProduct] = useState({ 12 | userId: authContext.user, 13 | name: "", 14 | manufacturer: "", 15 | description: "", 16 | }); 17 | console.log("----",product) 18 | const [open, setOpen] = useState(true); 19 | const cancelButtonRef = useRef(null); 20 | 21 | const handleInputChange = (key, value) => { 22 | setProduct({ ...product, [key]: value }); 23 | }; 24 | 25 | const addProduct = () => { 26 | fetch("http://localhost:4000/api/product/add", { 27 | method: "POST", 28 | headers: { 29 | "Content-type": "application/json", 30 | }, 31 | body: JSON.stringify(product), 32 | }) 33 | .then((result) => { 34 | alert("Product ADDED"); 35 | handlePageUpdate(); 36 | addProductModalSetting(); 37 | }) 38 | .catch((err) => console.log(err)); 39 | }; 40 | 41 | return ( 42 | // Modal 43 | 44 | 50 | 59 |
60 | 61 | 62 |
63 |
64 | 73 | 74 |
75 |
76 |
77 |
82 |
83 | 87 | Add Product 88 | 89 |
90 |
91 |
92 | 98 | 104 | handleInputChange(e.target.name, e.target.value) 105 | } 106 | className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" 107 | placeholder="Ex. Apple iMac 27“" 108 | /> 109 |
110 |
111 | 117 | 123 | handleInputChange(e.target.name, e.target.value) 124 | } 125 | className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" 126 | placeholder="Ex. Apple" 127 | /> 128 |
129 | {/*
130 | 136 | 142 | handleInputChange(e.target.name, e.target.value) 143 | } 144 | className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" 145 | placeholder="$299" 146 | /> 147 |
148 |
149 | 155 | 161 | handleInputChange(e.target.name, e.target.value) 162 | } 163 | className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" 164 | placeholder="0 - 999" 165 | /> 166 |
*/} 167 | 168 |
169 | 175 | 192 |
193 |
194 |
195 | {/* */} 201 | {/* */} 219 |
220 |
221 |
222 |
223 |
224 |
225 | 232 | 240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 | ); 248 | } 249 | -------------------------------------------------------------------------------- /Frontend/src/components/AddPurchaseDetails.js: -------------------------------------------------------------------------------- 1 | import { Fragment, useRef, useState } from "react"; 2 | import { Dialog, Transition } from "@headlessui/react"; 3 | import { PlusIcon } from "@heroicons/react/24/outline"; 4 | 5 | export default function AddPurchaseDetails({ 6 | addSaleModalSetting, 7 | products, 8 | handlePageUpdate, 9 | authContext 10 | }) { 11 | const [purchase, setPurchase] = useState({ 12 | userID: authContext.user, 13 | productID: "", 14 | quantityPurchased: "", 15 | purchaseDate: "", 16 | totalPurchaseAmount: "", 17 | }); 18 | const [open, setOpen] = useState(true); 19 | const cancelButtonRef = useRef(null); 20 | 21 | console.log("PPu: ", purchase); 22 | 23 | // Handling Input Change for input fields 24 | const handleInputChange = (key, value) => { 25 | setPurchase({ ...purchase, [key]: value }); 26 | }; 27 | 28 | // POST Data 29 | const addSale = () => { 30 | fetch("http://localhost:4000/api/purchase/add", { 31 | method: "POST", 32 | headers: { 33 | "Content-type": "application/json", 34 | }, 35 | body: JSON.stringify(purchase), 36 | }) 37 | .then((result) => { 38 | alert("Purchase ADDED"); 39 | handlePageUpdate(); 40 | addSaleModalSetting(); 41 | }) 42 | .catch((err) => console.log(err)); 43 | }; 44 | 45 | return ( 46 | // Modal 47 | 48 | 54 | 63 |
64 | 65 | 66 |
67 |
68 | 77 | 78 |
79 |
80 |
81 |
86 |
87 | 91 | Purchase Details 92 | 93 |
94 |
95 |
96 | 102 | 119 |
120 |
121 | 127 | 133 | handleInputChange(e.target.name, e.target.value) 134 | } 135 | className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" 136 | placeholder="0 - 999" 137 | /> 138 |
139 |
140 | 146 | 152 | handleInputChange(e.target.name, e.target.value) 153 | } 154 | className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" 155 | placeholder="$299" 156 | /> 157 |
158 |
159 | {/* */} 164 | 170 | 177 | handleInputChange(e.target.name, e.target.value) 178 | } 179 | /> 180 |
181 |
182 |
183 | {/* */} 189 | {/* */} 207 |
208 |
209 |
210 |
211 |
212 |
213 | 220 | 228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 | ); 236 | } 237 | -------------------------------------------------------------------------------- /Frontend/src/components/AddSale.js: -------------------------------------------------------------------------------- 1 | import { Fragment, useRef, useState } from "react"; 2 | import { Dialog, Transition } from "@headlessui/react"; 3 | import { PlusIcon } from "@heroicons/react/24/outline"; 4 | 5 | export default function AddSale({ 6 | addSaleModalSetting, 7 | products, 8 | stores, 9 | handlePageUpdate, 10 | authContext 11 | }) { 12 | const [sale, setSale] = useState({ 13 | userID: authContext.user, 14 | productID: "", 15 | storeID: "", 16 | stockSold: "", 17 | saleDate: "", 18 | totalSaleAmount: "", 19 | }); 20 | const [open, setOpen] = useState(true); 21 | const cancelButtonRef = useRef(null); 22 | 23 | 24 | // Handling Input Change for input fields 25 | const handleInputChange = (key, value) => { 26 | setSale({ ...sale, [key]: value }); 27 | }; 28 | 29 | // POST Data 30 | const addSale = () => { 31 | fetch("http://localhost:4000/api/sales/add", { 32 | method: "POST", 33 | headers: { 34 | "Content-type": "application/json", 35 | }, 36 | body: JSON.stringify(sale), 37 | }) 38 | .then((result) => { 39 | alert("Sale ADDED"); 40 | handlePageUpdate(); 41 | addSaleModalSetting(); 42 | }) 43 | .catch((err) => console.log(err)); 44 | }; 45 | 46 | return ( 47 | // Modal 48 | 49 | 55 | 64 |
65 | 66 | 67 |
68 |
69 | 78 | 79 |
80 |
81 |
82 |
87 |
88 | 92 | Add Sale 93 | 94 |
95 |
96 |
97 | 103 | 120 |
121 |
122 | 128 | 134 | handleInputChange(e.target.name, e.target.value) 135 | } 136 | className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" 137 | placeholder="0 - 999" 138 | /> 139 |
140 | 141 |
142 | 148 | 165 |
166 |
167 | 173 | 179 | handleInputChange(e.target.name, e.target.value) 180 | } 181 | className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" 182 | placeholder="$299" 183 | /> 184 |
185 |
186 | {/* */} 191 | 197 | 204 | handleInputChange(e.target.name, e.target.value) 205 | } 206 | /> 207 |
208 |
209 |
210 | {/* */} 216 | {/* */} 234 |
235 |
236 |
237 |
238 |
239 |
240 | 247 | 255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 | ); 263 | } 264 | -------------------------------------------------------------------------------- /Frontend/src/components/AddStore.js: -------------------------------------------------------------------------------- 1 | import { Fragment, useRef, useState, useContext } from "react"; 2 | import { Dialog, Transition } from "@headlessui/react"; 3 | import { PlusIcon } from "@heroicons/react/24/outline"; 4 | import UploadImage from "./UploadImage"; 5 | import AuthContext from "../AuthContext"; 6 | 7 | export default function AddStore() { 8 | const authContext = useContext(AuthContext); 9 | const [form, setForm] = useState({ 10 | userId: authContext.user, 11 | name: "", 12 | category: "", 13 | address: "", 14 | city: "", 15 | image: "", 16 | }); 17 | 18 | const handleInputChange = (e) => { 19 | setForm({ ...form, [e.target.name]: e.target.value }); 20 | }; 21 | 22 | const [open, setOpen] = useState(true); 23 | const cancelButtonRef = useRef(null); 24 | 25 | const addProduct = () => { 26 | fetch("http://localhost:4000/api/store/add", { 27 | method: "POST", 28 | headers: { 29 | "Content-type": "application/json", 30 | }, 31 | body: JSON.stringify(form), 32 | }) 33 | .then((result) => { 34 | alert("STORE ADDED"); 35 | setOpen(false); 36 | }) 37 | .catch((err) => console.log(err)); 38 | }; 39 | 40 | // Uploading image to cloudinary 41 | const uploadImage = async (image) => { 42 | const data = new FormData(); 43 | data.append("file", image); 44 | data.append("upload_preset", "inventoryapp"); 45 | 46 | await fetch("https://api.cloudinary.com/v1_1/ddhayhptm/image/upload", { 47 | method: "POST", 48 | body: data, 49 | }) 50 | .then((res) => res.json()) 51 | .then((data) => { 52 | setForm({ ...form, image: data.url }); 53 | alert("Store Image Successfully Uploaded"); 54 | }) 55 | .catch((error) => console.log(error)); 56 | }; 57 | 58 | return ( 59 | // Modal 60 | 61 | 67 | 76 |
77 | 78 | 79 |
80 |
81 | 90 | 91 |
92 |
93 |
94 |
99 |
100 | 104 | Store Information 105 | 106 |
107 |
108 |
109 | 115 | 124 |
125 |
126 | 132 | 141 |
142 |
143 | 149 | 167 |
168 |
169 | 175 | 184 |
185 |
186 |
187 |
188 | 189 | {/* 195 | */} 200 |
201 | 202 | {/* */} 208 | {/* */} 226 |
227 |
228 |
229 |
230 |
231 |
232 | 239 | 247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 | ); 255 | } 256 | -------------------------------------------------------------------------------- /Frontend/src/components/Header.js: -------------------------------------------------------------------------------- 1 | import { Fragment, useContext } from "react"; 2 | import { Disclosure, Menu, Transition } from "@headlessui/react"; 3 | import { Bars3Icon, BellIcon, XMarkIcon } from "@heroicons/react/24/outline"; 4 | import AuthContext from "../AuthContext"; 5 | import { Link } from "react-router-dom"; 6 | 7 | const navigation = [ 8 | { name: "Dashboard", href: "/", current: true }, 9 | { name: "Inventory", href: "/inventory", current: false }, 10 | { name: "Purchase Details", href: "/purchase-details", current: false }, 11 | { name: "Sales", href: "/sales", current: false }, 12 | { name: "Manage Store", href: "/manage-store", current: false }, 13 | ]; 14 | 15 | const userNavigation = [{ name: "Sign out", href: "./login" }]; 16 | 17 | function classNames(...classes) { 18 | return classes.filter(Boolean).join(" "); 19 | } 20 | 21 | export default function Header() { 22 | const authContext = useContext(AuthContext); 23 | const localStorageData = JSON.parse(localStorage.getItem("user")); 24 | return ( 25 | <> 26 |
27 | 28 | {({ open }) => ( 29 | <> 30 |
31 |
32 |
33 |
34 |
35 | Inventory Management System 40 | 41 | Inventory Management 42 | 43 |
44 |
45 |
46 |
47 |
48 | 55 | 56 | {/* Profile dropdown */} 57 | 58 |
59 | 60 | Open user menu 61 | profile 66 | 67 |
68 | 77 | 78 | {userNavigation.map((item) => ( 79 | 80 | {({ active }) => ( 81 | 88 | authContext.signout()}> 89 | {item.name}{" "} 90 | 91 | 92 | )} 93 | 94 | ))} 95 | 96 | 97 |
98 |
99 |
100 |
101 | {/* Mobile menu button */} 102 | 103 | Open main menu 104 | {open ? ( 105 | 116 |
117 |
118 |
119 | 120 | 121 |
122 | {navigation.map((item) => ( 123 | 124 | 136 | {item.name} 137 | 138 | 139 | ))} 140 |
141 |
142 |
143 |
144 | profile 149 |
150 |
151 |
152 | {localStorageData.firstName + 153 | " " + 154 | localStorageData.lastName} 155 |
156 |
157 | {localStorageData.email} 158 |
159 |
160 | 167 |
168 |
169 | {userNavigation.map((item) => ( 170 | 176 | authContext.signout()}> 177 | {item.name}{" "} 178 | 179 | 180 | ))} 181 |
182 |
183 |
184 | 185 | )} 186 |
187 |
188 | 189 | ); 190 | } 191 | -------------------------------------------------------------------------------- /Frontend/src/components/Layout.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Outlet } from "react-router-dom"; 3 | import Header from "./Header"; 4 | import SideMenu from "./SideMenu"; 5 | 6 | function Layout() { 7 | return ( 8 | <> 9 |
10 |
11 |
12 |
13 |
14 | 15 |
16 | 17 |
18 | 19 | ); 20 | } 21 | 22 | export default Layout; 23 | -------------------------------------------------------------------------------- /Frontend/src/components/SideMenu.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | 4 | function SideMenu() { 5 | const localStorageData = JSON.parse(localStorage.getItem("user")); 6 | 7 | return ( 8 |
9 |
10 | 68 |
69 | 70 |
71 |
72 | Profile 77 | 78 |
79 |

80 | 81 | {localStorageData.firstName + " " + localStorageData.lastName} 82 | 83 | 84 | {localStorageData.email} 85 |

86 |
87 |
88 |
89 |
90 | ); 91 | } 92 | 93 | export default SideMenu; 94 | -------------------------------------------------------------------------------- /Frontend/src/components/UpdateProduct.js: -------------------------------------------------------------------------------- 1 | import { Fragment, useRef, useState } from "react"; 2 | import { Dialog, Transition } from "@headlessui/react"; 3 | import { PlusIcon } from "@heroicons/react/24/outline"; 4 | 5 | export default function UpdateProduct({ 6 | updateProductData, 7 | updateModalSetting, 8 | }) { 9 | const { _id, name, manufacturer, description } = updateProductData; 10 | const [product, setProduct] = useState({ 11 | productID: _id, 12 | name: name, 13 | manufacturer: manufacturer, 14 | description: description, 15 | }); 16 | const [open, setOpen] = useState(true); 17 | const cancelButtonRef = useRef(null); 18 | 19 | const handleInputChange = (key, value) => { 20 | console.log(key); 21 | setProduct({ ...product, [key]: value }); 22 | }; 23 | 24 | const updateProduct = () => { 25 | fetch("http://localhost:4000/api/product/update", { 26 | method: "POST", 27 | headers: { 28 | "Content-type": "application/json", 29 | }, 30 | body: JSON.stringify(product), 31 | }) 32 | .then((result) => { 33 | alert("Product Updated"); 34 | setOpen(false); 35 | }) 36 | .catch((err) => console.log(err)); 37 | }; 38 | 39 | return ( 40 | // Modal 41 | 42 | 48 | 57 |
58 | 59 | 60 |
61 |
62 | 71 | 72 |
73 |
74 |
75 |
80 |
81 | 85 | Update Product 86 | 87 |
88 |
89 |
90 | 96 | 102 | handleInputChange(e.target.name, e.target.value) 103 | } 104 | className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" 105 | placeholder="Ex. Apple iMac 27“" 106 | /> 107 |
108 |
109 | 115 | 121 | handleInputChange(e.target.name, e.target.value) 122 | } 123 | className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" 124 | placeholder="Ex. Apple" 125 | /> 126 |
127 |
128 | 134 | 151 |
152 |
153 |
154 | {/* */} 160 | {/* */} 178 |
179 |
180 |
181 |
182 |
183 |
184 | 191 | 199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 | ); 207 | } 208 | -------------------------------------------------------------------------------- /Frontend/src/components/UploadImage.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | 3 | function UploadImage({ uploadImage }) { 4 | const [fileName, setFileName] = useState(""); 5 | 6 | const handleFileInputChange = (event) => { 7 | setFileName(event.target.files[0]); 8 | uploadImage(event.target.files[0]); 9 | }; 10 | 11 | return ( 12 |
13 | 33 | 41 |
42 | ); 43 | } 44 | 45 | export default UploadImage; 46 | -------------------------------------------------------------------------------- /Frontend/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | 6 | body { 7 | margin: 0; 8 | padding: 0; 9 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 10 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 11 | sans-serif; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | } 15 | 16 | code { 17 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 18 | monospace; 19 | } 20 | -------------------------------------------------------------------------------- /Frontend/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const root = ReactDOM.createRoot(document.getElementById('root')); 8 | root.render( 9 | 10 | 11 | 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /Frontend/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Frontend/src/pages/Dashboard.js: -------------------------------------------------------------------------------- 1 | import React, { useContext, useEffect, useState } from "react"; 2 | import Chart from "react-apexcharts"; 3 | import AuthContext from "../AuthContext"; 4 | import { Doughnut } from "react-chartjs-2"; 5 | import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js"; 6 | 7 | ChartJS.register(ArcElement, Tooltip, Legend); 8 | export const data = { 9 | labels: ["Apple", "Knorr", "Shoop", "Green", "Purple", "Orange"], 10 | datasets: [ 11 | { 12 | label: "# of Votes", 13 | data: [0, 1, 5, 8, 9, 15], 14 | backgroundColor: [ 15 | "rgba(255, 99, 132, 0.2)", 16 | "rgba(54, 162, 235, 0.2)", 17 | "rgba(255, 206, 86, 0.2)", 18 | "rgba(75, 192, 192, 0.2)", 19 | "rgba(153, 102, 255, 0.2)", 20 | "rgba(255, 159, 64, 0.2)", 21 | ], 22 | borderColor: [ 23 | "rgba(255, 99, 132, 1)", 24 | "rgba(54, 162, 235, 1)", 25 | "rgba(255, 206, 86, 1)", 26 | "rgba(75, 192, 192, 1)", 27 | "rgba(153, 102, 255, 1)", 28 | "rgba(255, 159, 64, 1)", 29 | ], 30 | borderWidth: 1, 31 | }, 32 | ], 33 | }; 34 | 35 | function Dashboard() { 36 | const [saleAmount, setSaleAmount] = useState(""); 37 | const [purchaseAmount, setPurchaseAmount] = useState(""); 38 | const [stores, setStores] = useState([]); 39 | const [products, setProducts] = useState([]); 40 | 41 | const [chart, setChart] = useState({ 42 | options: { 43 | chart: { 44 | id: "basic-bar", 45 | }, 46 | xaxis: { 47 | categories: [ 48 | "Jan", 49 | "Feb", 50 | "Mar", 51 | "Apr", 52 | "May", 53 | "Jun", 54 | "Jul", 55 | "Aug", 56 | "Sep", 57 | "Oct", 58 | "Nov", 59 | "Dec", 60 | ], 61 | }, 62 | }, 63 | series: [ 64 | { 65 | name: "series", 66 | data: [10, 20, 40, 50, 60, 20, 10, 35, 45, 70, 25, 70], 67 | }, 68 | ], 69 | }); 70 | 71 | // Update Chart Data 72 | const updateChartData = (salesData) => { 73 | setChart({ 74 | ...chart, 75 | series: [ 76 | { 77 | name: "Monthly Sales Amount", 78 | data: [...salesData], 79 | }, 80 | ], 81 | }); 82 | }; 83 | 84 | const authContext = useContext(AuthContext); 85 | 86 | useEffect(() => { 87 | fetchTotalSaleAmount(); 88 | fetchTotalPurchaseAmount(); 89 | fetchStoresData(); 90 | fetchProductsData(); 91 | fetchMonthlySalesData(); 92 | }, []); 93 | 94 | // Fetching total sales amount 95 | const fetchTotalSaleAmount = () => { 96 | fetch( 97 | `http://localhost:4000/api/sales/get/${authContext.user}/totalsaleamount` 98 | ) 99 | .then((response) => response.json()) 100 | .then((datas) => setSaleAmount(datas.totalSaleAmount)); 101 | }; 102 | 103 | // Fetching total purchase amount 104 | const fetchTotalPurchaseAmount = () => { 105 | fetch( 106 | `http://localhost:4000/api/purchase/get/${authContext.user}/totalpurchaseamount` 107 | ) 108 | .then((response) => response.json()) 109 | .then((datas) => setPurchaseAmount(datas.totalPurchaseAmount)); 110 | }; 111 | 112 | // Fetching all stores data 113 | const fetchStoresData = () => { 114 | fetch(`http://localhost:4000/api/store/get/${authContext.user}`) 115 | .then((response) => response.json()) 116 | .then((datas) => setStores(datas)); 117 | }; 118 | 119 | // Fetching Data of All Products 120 | const fetchProductsData = () => { 121 | fetch(`http://localhost:4000/api/product/get/${authContext.user}`) 122 | .then((response) => response.json()) 123 | .then((datas) => setProducts(datas)) 124 | .catch((err) => console.log(err)); 125 | }; 126 | 127 | // Fetching Monthly Sales 128 | const fetchMonthlySalesData = () => { 129 | fetch(`http://localhost:4000/api/sales/getmonthly`) 130 | .then((response) => response.json()) 131 | .then((datas) => updateChartData(datas.salesAmount)) 132 | .catch((err) => console.log(err)); 133 | }; 134 | 135 | return ( 136 | <> 137 |
138 |
139 |
140 | 147 | 153 | 154 | 155 | 67.81% 156 |
157 | 158 |
159 | 160 | Sales 161 | 162 | 163 |

164 | 165 | ${saleAmount} 166 | 167 | 168 | from $240.94 169 |

170 |
171 |
172 | 173 |
174 |
175 | 182 | 188 | 189 | 190 | 67.81% 191 |
192 | 193 |
194 | 195 | Purchase 196 | 197 | 198 |

199 | 200 | {" "} 201 | ${purchaseAmount}{" "} 202 | 203 | 204 | from $404.32 205 |

206 |
207 |
208 |
209 |
210 | 217 | 223 | 224 | 225 | 67.81% 226 |
227 | 228 |
229 | 230 | Total Products 231 | 232 | 233 |

234 | 235 | {" "} 236 | {products.length}{" "} 237 | 238 | 239 | {/* from $404.32 */} 240 |

241 |
242 |
243 |
244 |
245 | 252 | 258 | 259 | 260 | 67.81% 261 |
262 | 263 |
264 | 265 | Total Stores 266 | 267 | 268 |

269 | 270 | {" "} 271 | {stores.length}{" "} 272 | 273 | 274 | {/* from 0 */} 275 |

276 |
277 |
278 |
279 |
280 | 286 |
287 |
288 | 289 |
290 |
291 |
292 | 293 | ); 294 | } 295 | 296 | export default Dashboard; 297 | -------------------------------------------------------------------------------- /Frontend/src/pages/Inventory.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useContext } from "react"; 2 | import AddProduct from "../components/AddProduct"; 3 | import UpdateProduct from "../components/UpdateProduct"; 4 | import AuthContext from "../AuthContext"; 5 | 6 | function Inventory() { 7 | const [showProductModal, setShowProductModal] = useState(false); 8 | const [showUpdateModal, setShowUpdateModal] = useState(false); 9 | const [updateProduct, setUpdateProduct] = useState([]); 10 | const [products, setAllProducts] = useState([]); 11 | const [searchTerm, setSearchTerm] = useState(); 12 | const [updatePage, setUpdatePage] = useState(true); 13 | const [stores, setAllStores] = useState([]); 14 | 15 | const authContext = useContext(AuthContext); 16 | console.log('===================================='); 17 | console.log(authContext); 18 | console.log('===================================='); 19 | 20 | useEffect(() => { 21 | fetchProductsData(); 22 | fetchSalesData(); 23 | }, [updatePage]); 24 | 25 | // Fetching Data of All Products 26 | const fetchProductsData = () => { 27 | fetch(`http://localhost:4000/api/product/get/${authContext.user}`) 28 | .then((response) => response.json()) 29 | .then((data) => { 30 | setAllProducts(data); 31 | }) 32 | .catch((err) => console.log(err)); 33 | }; 34 | 35 | // Fetching Data of Search Products 36 | const fetchSearchData = () => { 37 | fetch(`http://localhost:4000/api/product/search?searchTerm=${searchTerm}`) 38 | .then((response) => response.json()) 39 | .then((data) => { 40 | setAllProducts(data); 41 | }) 42 | .catch((err) => console.log(err)); 43 | }; 44 | 45 | // Fetching all stores data 46 | const fetchSalesData = () => { 47 | fetch(`http://localhost:4000/api/store/get/${authContext.user}`) 48 | .then((response) => response.json()) 49 | .then((data) => { 50 | setAllStores(data); 51 | }); 52 | }; 53 | 54 | // Modal for Product ADD 55 | const addProductModalSetting = () => { 56 | setShowProductModal(!showProductModal); 57 | }; 58 | 59 | // Modal for Product UPDATE 60 | const updateProductModalSetting = (selectedProductData) => { 61 | console.log("Clicked: edit"); 62 | setUpdateProduct(selectedProductData); 63 | setShowUpdateModal(!showUpdateModal); 64 | }; 65 | 66 | 67 | // Delete item 68 | const deleteItem = (id) => { 69 | console.log("Product ID: ", id); 70 | console.log(`http://localhost:4000/api/product/delete/${id}`); 71 | fetch(`http://localhost:4000/api/product/delete/${id}`) 72 | .then((response) => response.json()) 73 | .then((data) => { 74 | setUpdatePage(!updatePage); 75 | }); 76 | }; 77 | 78 | // Handle Page Update 79 | const handlePageUpdate = () => { 80 | setUpdatePage(!updatePage); 81 | }; 82 | 83 | // Handle Search Term 84 | const handleSearchTerm = (e) => { 85 | setSearchTerm(e.target.value); 86 | fetchSearchData(); 87 | }; 88 | 89 | return ( 90 |
91 |
92 |
93 | Overall Inventory 94 |
95 |
96 | 97 | Total Products 98 | 99 | 100 | {products.length} 101 | 102 | 103 | Last 7 days 104 | 105 |
106 |
107 | 108 | Stores 109 | 110 |
111 |
112 | 113 | {stores.length} 114 | 115 | 116 | Last 7 days 117 | 118 |
119 |
120 | 121 | $2000 122 | 123 | 124 | Revenue 125 | 126 |
127 |
128 |
129 |
130 | 131 | Top Selling 132 | 133 |
134 |
135 | 136 | 5 137 | 138 | 139 | Last 7 days 140 | 141 |
142 |
143 | 144 | $1500 145 | 146 | Cost 147 |
148 |
149 |
150 |
151 | 152 | Low Stocks 153 | 154 |
155 |
156 | 157 | 12 158 | 159 | 160 | Ordered 161 | 162 |
163 |
164 | 165 | 2 166 | 167 | 168 | Not in Stock 169 | 170 |
171 |
172 |
173 |
174 |
175 | 176 | {showProductModal && ( 177 | 181 | )} 182 | {showUpdateModal && ( 183 | 187 | )} 188 | 189 | {/* Table */} 190 |
191 |
192 |
193 | Products 194 |
195 | search-icon 200 | 207 |
208 |
209 |
210 | 217 |
218 |
219 | 220 | 221 | 222 | 225 | 228 | 231 | 234 | 237 | 240 | 241 | 242 | 243 | 244 | {products.map((element, index) => { 245 | return ( 246 | 247 | 250 | 253 | 256 | 259 | 262 | 276 | 277 | ); 278 | })} 279 | 280 |
223 | Products 224 | 226 | Manufacturer 227 | 229 | Stock 230 | 232 | Description 233 | 235 | Availibility 236 | 238 | More 239 |
248 | {element.name} 249 | 251 | {element.manufacturer} 252 | 254 | {element.stock} 255 | 257 | {element.description} 258 | 260 | {element.stock > 0 ? "In Stock" : "Not in Stock"} 261 | 263 | updateProductModalSetting(element)} 266 | > 267 | Edit{" "} 268 | 269 | deleteItem(element._id)} 272 | > 273 | Delete 274 | 275 |
281 |
282 |
283 |
284 | ); 285 | } 286 | 287 | export default Inventory; 288 | -------------------------------------------------------------------------------- /Frontend/src/pages/Login.js: -------------------------------------------------------------------------------- 1 | // import { LockClosedIcon } from "@heroicons/react/20/solid"; 2 | import { useContext, useState } from "react"; 3 | import { Link, useNavigate } from "react-router-dom"; 4 | import AuthContext from "../AuthContext"; 5 | 6 | function Login() { 7 | const [form, setForm] = useState({ 8 | email: "", 9 | password: "", 10 | }); 11 | 12 | const authContext = useContext(AuthContext); 13 | const navigate = useNavigate(); 14 | 15 | 16 | const handleInputChange = (e) => { 17 | setForm({ ...form, [e.target.name]: e.target.value }); 18 | }; 19 | 20 | const authCheck = () => { 21 | setTimeout(() => { 22 | fetch("http://localhost:4000/api/login") 23 | .then((response) => response.json()) 24 | .then((data) => { 25 | alert("Successfully Login"); 26 | localStorage.setItem("user", JSON.stringify(data)); 27 | authContext.signin(data._id, () => { 28 | navigate("/"); 29 | }); 30 | }) 31 | .catch((err) => { 32 | alert("Wrong credentials, Try again") 33 | console.log(err); 34 | }); 35 | }, 3000); 36 | }; 37 | 38 | const loginUser = (e) => { 39 | // Cannot send empty data 40 | if (form.email === "" || form.password === "") { 41 | alert("To login user, enter details to proceed..."); 42 | } else { 43 | fetch("http://localhost:4000/api/login", { 44 | method: "POST", 45 | headers: { 46 | "Content-type": "application/json", 47 | }, 48 | body: JSON.stringify(form), 49 | }) 50 | .then((result) => { 51 | console.log("User login", result); 52 | }) 53 | .catch((error) => { 54 | console.log("Something went wrong ", error); 55 | }); 56 | } 57 | authCheck(); 58 | }; 59 | 60 | 61 | const handleSubmit = (e) => { 62 | e.preventDefault(); 63 | }; 64 | 65 | 66 | return ( 67 | <> 68 |
69 |
70 | 71 |
72 |
73 |
74 | Your Company 79 |

80 | Signin to your account 81 |

82 |

83 | Or 84 | 87 | start your 14-day free trial 88 | 89 |

90 |
91 |
92 | {/* */} 93 |
94 |
95 | 98 | 109 |
110 |
111 | 114 | 125 |
126 |
127 | 128 |
129 |
130 | 136 | 142 |
143 | 144 |
145 | 148 | Forgot your password? 149 | 150 |
151 |
152 | 153 |
154 | 167 |

168 | Or{" "} 169 | 172 | Don't Have an Account, Please{" "} 173 | Register now 174 | 175 |

176 |
177 |
178 |
179 |
180 | 181 | ); 182 | } 183 | 184 | export default Login; 185 | -------------------------------------------------------------------------------- /Frontend/src/pages/PurchaseDetails.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useContext } from "react"; 2 | import AddPurchaseDetails from "../components/AddPurchaseDetails"; 3 | import AuthContext from "../AuthContext"; 4 | 5 | function PurchaseDetails() { 6 | const [showPurchaseModal, setPurchaseModal] = useState(false); 7 | const [purchase, setAllPurchaseData] = useState([]); 8 | const [products, setAllProducts] = useState([]); 9 | const [updatePage, setUpdatePage] = useState(true); 10 | 11 | const authContext = useContext(AuthContext); 12 | 13 | useEffect(() => { 14 | fetchPurchaseData(); 15 | fetchProductsData(); 16 | }, [updatePage]); 17 | 18 | // Fetching Data of All Purchase items 19 | const fetchPurchaseData = () => { 20 | fetch(`http://localhost:4000/api/purchase/get/${authContext.user}`) 21 | .then((response) => response.json()) 22 | .then((data) => { 23 | setAllPurchaseData(data); 24 | }) 25 | .catch((err) => console.log(err)); 26 | }; 27 | 28 | // Fetching Data of All Products 29 | const fetchProductsData = () => { 30 | fetch(`http://localhost:4000/api/product/get/${authContext.user}`) 31 | .then((response) => response.json()) 32 | .then((data) => { 33 | setAllProducts(data); 34 | }) 35 | .catch((err) => console.log(err)); 36 | }; 37 | 38 | // Modal for Sale Add 39 | const addSaleModalSetting = () => { 40 | setPurchaseModal(!showPurchaseModal); 41 | }; 42 | 43 | 44 | // Handle Page Update 45 | const handlePageUpdate = () => { 46 | setUpdatePage(!updatePage); 47 | }; 48 | 49 | return ( 50 |
51 |
52 | {showPurchaseModal && ( 53 | 59 | )} 60 | {/* Table */} 61 |
62 |
63 |
64 | Purchase Details 65 |
66 |
67 | 74 |
75 |
76 | 77 | 78 | 79 | 82 | 85 | 88 | 91 | 92 | 93 | 94 | 95 | {purchase.map((element, index) => { 96 | return ( 97 | 98 | 101 | 104 | 110 | 113 | 114 | ); 115 | })} 116 | 117 |
80 | Product Name 81 | 83 | Quantity Purchased 84 | 86 | Purchase Date 87 | 89 | Total Purchase Amount 90 |
99 | {element.ProductID?.name} 100 | 102 | {element.QuantityPurchased} 103 | 105 | {new Date(element.PurchaseDate).toLocaleDateString() == 106 | new Date().toLocaleDateString() 107 | ? "Today" 108 | : element.PurchaseDate} 109 | 111 | ${element.TotalPurchaseAmount} 112 |
118 |
119 |
120 |
121 | ); 122 | } 123 | 124 | export default PurchaseDetails; 125 | -------------------------------------------------------------------------------- /Frontend/src/pages/Register.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { Link, useNavigate } from "react-router-dom"; 3 | import UploadImage from "../components/UploadImage"; 4 | 5 | function Register() { 6 | const [form, setForm] = useState({ 7 | firstName: "", 8 | lastName: "", 9 | email: "", 10 | password: "", 11 | phoneNumber: "", 12 | imageUrl: "", 13 | }); 14 | 15 | const navigate = useNavigate(); 16 | 17 | // Handling Input change for registration form. 18 | const handleInputChange = (e) => { 19 | setForm({ ...form, [e.target.name]: e.target.value }); 20 | }; 21 | 22 | // Register User 23 | const registerUser = () => { 24 | fetch("http://localhost:4000/api/register", { 25 | method: "POST", 26 | headers: { 27 | "Content-type": "application/json", 28 | }, 29 | body: JSON.stringify(form), 30 | }) 31 | .then((result) => { 32 | alert("Successfully Registered, Now Login with your details"); 33 | navigate('/login') 34 | 35 | }) 36 | .catch((err) => console.log(err)); 37 | }; 38 | // ------------------ 39 | 40 | // Uploading image to cloudinary 41 | const uploadImage = async (image) => { 42 | const data = new FormData(); 43 | data.append("file", image); 44 | data.append("upload_preset", "inventoryapp"); 45 | 46 | await fetch("https://api.cloudinary.com/v1_1/ddhayhptm/image/upload", { 47 | method: "POST", 48 | body: data, 49 | }) 50 | .then((res) => res.json()) 51 | .then((data) => { 52 | setForm({ ...form, imageUrl: data.url }); 53 | alert("Image Successfully Uploaded"); 54 | }) 55 | .catch((error) => console.log(error)); 56 | }; 57 | 58 | 59 | const handleSubmit = (e) => { 60 | e.preventDefault(); 61 | } 62 | 63 | return ( 64 | <> 65 |
66 |
67 |
68 | Your Company 73 |

74 | Register your account 75 |

76 |
77 |
78 | {/* */} 79 |
80 |
81 | 90 | 99 |
100 |
101 | 112 |
113 |
114 | 125 |
126 |
127 | 137 |
138 | 139 |
140 | 141 |
142 |
143 | 151 | 157 |
158 | 159 |
160 | 163 | Forgot your password? 164 | 165 |
166 |
167 | 168 |
169 | 182 |

183 | Or{" "} 184 | 187 | Already Have an Account, Please 188 | Signin now 189 | 190 |

191 |
192 |
193 |
194 |
195 | 196 |
197 |
198 | 199 | ); 200 | } 201 | 202 | export default Register; 203 | -------------------------------------------------------------------------------- /Frontend/src/pages/Sales.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useContext } from "react"; 2 | import AddSale from "../components/AddSale"; 3 | import AuthContext from "../AuthContext"; 4 | 5 | function Sales() { 6 | const [showSaleModal, setShowSaleModal] = useState(false); 7 | const [sales, setAllSalesData] = useState([]); 8 | const [products, setAllProducts] = useState([]); 9 | const [stores, setAllStores] = useState([]); 10 | const [updatePage, setUpdatePage] = useState(true); 11 | 12 | const authContext = useContext(AuthContext); 13 | 14 | useEffect(() => { 15 | fetchSalesData(); 16 | fetchProductsData(); 17 | fetchStoresData(); 18 | }, [updatePage]); 19 | 20 | // Fetching Data of All Sales 21 | const fetchSalesData = () => { 22 | fetch(`http://localhost:4000/api/sales/get/${authContext.user}`) 23 | .then((response) => response.json()) 24 | .then((data) => { 25 | setAllSalesData(data); 26 | }) 27 | .catch((err) => console.log(err)); 28 | }; 29 | 30 | // Fetching Data of All Products 31 | const fetchProductsData = () => { 32 | fetch(`http://localhost:4000/api/product/get/${authContext.user}`) 33 | .then((response) => response.json()) 34 | .then((data) => { 35 | setAllProducts(data); 36 | }) 37 | .catch((err) => console.log(err)); 38 | }; 39 | 40 | // Fetching Data of All Stores 41 | const fetchStoresData = () => { 42 | fetch(`http://localhost:4000/api/store/get/${authContext.user}`) 43 | .then((response) => response.json()) 44 | .then((data) => { 45 | setAllStores(data); 46 | }); 47 | }; 48 | 49 | // Modal for Sale Add 50 | const addSaleModalSetting = () => { 51 | setShowSaleModal(!showSaleModal); 52 | }; 53 | 54 | // Handle Page Update 55 | const handlePageUpdate = () => { 56 | setUpdatePage(!updatePage); 57 | }; 58 | 59 | return ( 60 |
61 |
62 | {showSaleModal && ( 63 | 70 | )} 71 | {/* Table */} 72 |
73 |
74 |
75 | Sales 76 |
77 |
78 | 85 |
86 |
87 | 88 | 89 | 90 | 93 | 96 | 99 | 102 | 105 | 106 | 107 | 108 | 109 | {sales.map((element, index) => { 110 | return ( 111 | 112 | 115 | 118 | 121 | 124 | 127 | 128 | ); 129 | })} 130 | 131 |
91 | Product Name 92 | 94 | Store Name 95 | 97 | Stock Sold 98 | 100 | Sales Date 101 | 103 | Total Sale Amount 104 |
113 | {element.ProductID?.name} 114 | 116 | {element.StoreID?.name} 117 | 119 | {element.StockSold} 120 | 122 | {element.SaleDate} 123 | 125 | ${element.TotalSaleAmount} 126 |
132 |
133 |
134 |
135 | ); 136 | } 137 | 138 | export default Sales; 139 | -------------------------------------------------------------------------------- /Frontend/src/pages/Store.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useContext } from "react"; 2 | import AddStore from "../components/AddStore"; 3 | import AuthContext from "../AuthContext"; 4 | 5 | function Store() { 6 | const [showModal, setShowModal] = useState(false); 7 | const [stores, setAllStores] = useState([]); 8 | 9 | const authContext = useContext(AuthContext); 10 | 11 | useEffect(() => { 12 | fetchData(); 13 | }, []); 14 | 15 | // Fetching all stores data 16 | const fetchData = () => { 17 | fetch(`http://localhost:4000/api/store/get/${authContext.user}`) 18 | .then((response) => response.json()) 19 | .then((data) => { 20 | setAllStores(data); 21 | }); 22 | }; 23 | 24 | const modalSetting = () => { 25 | setShowModal(!showModal); 26 | }; 27 | 28 | return ( 29 |
30 |
31 |
32 | Manage Store 33 | 39 |
40 | {showModal && } 41 | {stores.map((element, index) => { 42 | return ( 43 |
47 |
48 | store 53 |
54 |
55 | {element.name} 56 |
57 | location-icon 62 | {element.address + ", " + element.city} 63 |
64 |
65 |
66 | ); 67 | })} 68 |
69 |
70 | ); 71 | } 72 | 73 | export default Store; 74 | -------------------------------------------------------------------------------- /Frontend/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /Frontend/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /Frontend/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./src/**/*.{js,jsx,ts,tsx}", 5 | ], 6 | theme: { 7 | extend: {}, 8 | }, 9 | plugins: [ 10 | // ... 11 | require("@tailwindcss/forms"), 12 | ], 13 | }; 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React-Inventory-Management-System 2 | Inventory Management System Built with React JS, Node JS, Express JS, MongoDB and Tailwind CSS. 3 | 4 | ### Show Some Support! 5 | [![Buy Me A Coffee](https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png)](https://www.buymeacoffee.com/hamzashaikh) 6 | 7 | 8 | # [View Live Preview from here.](https://inventory-management-rosy.vercel.app) 9 | --------------------------------------------------------------------------------