From ae13816aa934eecc2b97e15796f08f64f72fad71 Mon Sep 17 00:00:00 2001 From: Sibunnayak Date: Tue, 16 Apr 2024 15:32:11 +0530 Subject: [PATCH] point of sale --- src/_nav.js | 8 +- src/routes.js | 7 + src/views/PointOfSale/Pos.js | 987 +++++++++++++++++++++++++++++++++++ 3 files changed, 1001 insertions(+), 1 deletion(-) create mode 100644 src/views/PointOfSale/Pos.js diff --git a/src/_nav.js b/src/_nav.js index 2e8ec6a..fbf0b81 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -306,7 +306,13 @@ const _nav = [ icon: , to: "/blogs", }, - +//Point of Sale start +{ + component: CNavItem, + name: "Point of Sale", + icon: , + to: "/pos", +}, // { // component: CNavGroup, // name: "Blog", diff --git a/src/routes.js b/src/routes.js index b972177..c81ac74 100644 --- a/src/routes.js +++ b/src/routes.js @@ -136,6 +136,7 @@ import CityRevenueCharts from "./views/Charts/CityRevenue"; import { element } from "prop-types"; import OrderdayChart from "./views/Charts/OrderDaywise"; import RevenueCharts from "./views/Charts/RevenueCharts"; +import Pos from "./views/PointOfSale/Pos"; const routes = [ { path: "/", exact: true, name: "Home" }, { @@ -593,6 +594,12 @@ const routes = [ name: "Revenue (Day Wise)", element: RevenueCharts, }, + //Point of Sale Section + { + path: "/pos", + name: "Point of Sale", + element: Pos, + }, ]; export default routes; diff --git a/src/views/PointOfSale/Pos.js b/src/views/PointOfSale/Pos.js new file mode 100644 index 0000000..1aaaf5f --- /dev/null +++ b/src/views/PointOfSale/Pos.js @@ -0,0 +1,987 @@ +import React, { useState, useEffect } from "react"; +import { Link } from "react-router-dom"; +import Button from "@material-ui/core/Button"; +import { useNavigate } from "react-router-dom"; +import axios from "axios"; +import { isAutheticated } from "src/auth"; +import swal from "sweetalert"; +import { + Box, + FormControl, + IconButton, + InputLabel, + MenuItem, + Select, + TextField, + Container, + Grid, + Paper, + Typography, +} from "@mui/material"; + +import SearchIcon from "@mui/icons-material/Search"; +import ClearIcon from "@mui/icons-material/Clear"; +// import PercentIcon from "@mui/icons-material/Percent"; +import Table from "@mui/material/Table"; +import TableBody from "@mui/material/TableBody"; +import TableCell from "@mui/material/TableCell"; +import TableContainer from "@mui/material/TableContainer"; +import TableHead from "@mui/material/TableHead"; +import TableRow from "@mui/material/TableRow"; + +const Pos = () => { + const token = isAutheticated(); + const [query, setQuery] = useState(""); + const navigate = useNavigate(); + const [loading, setLoading] = useState(true); + const [success, setSuccess] = useState(true); + const [posData, setPosData] = useState([]); + const [user, setUser] = useState([ + // { + // id: 1, + // first_Name: "John", + // last_Name: "Doe", + // street: "123 Main St", + // city: "New York", + // state: "NY", + // country: "USA", + // postalCode: "10001", + // phone_Number: "123-456-7890", + // }, + // { + // id: 2, + // first_Name: "Jane", + // last_Name: "Smith", + // street: "456 Elm St", + // city: "Los Angeles", + // state: "CA", + // country: "USA", + // postalCode: "90001", + // phone_Number: "123-456-7890", + // }, + // { + // id: 3, + // first_Name: "Michael", + // last_Name: "Johnson", + // street: "789 Oak St", + // city: "Chicago", + // state: "IL", + // country: "USA", + // postalCode: "60007", + // phone_Number: "123-456-7890", + // }, + // { + // id: 4, + // first_Name: "Sarah", + // last_Name: "Williams", + // street: "101 Pine St", + // city: "Miami", + // state: "FL", + // country: "USA", + // postalCode: "33101", + // phone_Number: "123-456-7890", + // }, + // { + // id: 5, + // first_Name: "John", + // last_Name: "Doe", + // street: " Main St", + // city: "New York", + // state: "NY", + // country: "USA", + // postalCode: "10001", + // phone_Number: "123-122-3210", + // }, + ]); + const getUsers = async () => { + axios + .get(`/api/v1/admin/users`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + setUser(res.data.users); + setLoading(false); + }) + .catch((error) => { + swal({ + title: error, + text: "please login to access the resource or refresh the page ", + icon: "error", + button: "Retry", + dangerMode: true, + }); + setLoading(false); + }); + }; + const [showData, setShowData] = useState(user); + const [currentUser, setCurrentUser] = useState(null); + const [salesType, setSalesType] = useState(""); + const [storedelivery, setStoreDelivery] = useState(""); + + // Function to handle change in radio button selection + const handleSalesTypeChange = (event) => { + setSalesType(event.target.value); + }; + const handlestoredeliveryChange = (event) => { + setStoreDelivery(event.target.value); + }; + useEffect(() => { + setTimeout(() => { + if (query !== "") { + setCurrentUser(null); + const lowerCaseQuery = query.toLowerCase(); // Convert query to lowercase + + const searchedResult = user.filter((item) => + item.name.toString().toLowerCase().includes(lowerCaseQuery) + ); + + setShowData(searchedResult); + setLoading(false); + } + // else { + // setShowData(user); // Show all users when query is empty + // setCurrentUser(null); // Reset current user when query is empty + // } + }, 100); + }, [query]); + + const handleClick = (id) => { + setQuery(""); + const customer = user.find((user) => user.id === id); + setCurrentUser(customer); + }; + + // part 2*****************************8 + const [productData, setProductData] = useState([]); + const [filteredItems, setFilteredItems] = useState([]); + const [categories, setCategories] = useState([]); + const [selectedCategories, setSelectedCategories] = useState([]); + const [categoryValue, setCategoryValue] = useState("All"); + const [cartItem, setCartItem] = useState([]); + const [individualSubtotals, setIndividualSubtotals] = useState([]); + const [total, setTotal] = useState(0); + + const getAllProducts = async () => { + try { + const response = await axios.get("/api/product/getAll/"); + if (response.status === 200) { + // setProductData(response?.data?.product); + const activeProducts = response?.data?.product.filter( + (product) => product.product_Status === "Active" + ); + setProductData(activeProducts); + } + } catch (error) { + console.error("Error fetching products:", error); + } + }; + + const getCaterogy = async () => { + try { + const response = await axios.get("/api/category/getCategories"); + if (response.status === 200) { + setCategories(response?.data?.categories); + } + } catch (error) { + console.error("Error fetching categories:", error); + } + }; + const handleChange = (event) => { + const { name, value } = event.target; + + if (name === "category") { + setCategoryValue(value); + setSelectedCategories((prevCategories) => { + if (prevCategories.includes(value)) { + return prevCategories.filter((category) => category !== value); + } else { + return [...prevCategories, value]; + } + }); + } + }; + const items = () => { + setFilteredItems( + productData?.filter((item) => { + const categoryMatch = + categoryValue === "All" || + item.category.categoryName === categoryValue; + return categoryMatch; + }) + ); + }; + + useEffect(() => { + setLoading(true); + getAllProducts() + .then(() => { + getCaterogy(); + }) + .catch((error) => { + console.error("Error fetching products:", error); + }) + .finally(() => { + setLoading(false); // Set loading to false after data fetching + }); + }, [token]); + + useEffect(() => { + items(); + }, [categoryValue, productData]); + const styles = { + selectHeading: { + fontFamily: "inter", + fontWeight: "600", + fontSize: "16px", + color: "#6C7275", + marginBottom: ".5rem", + }, + tableContainer: { + maxHeight: 360, + height: 360, + overflowY: "auto", // Enable vertical scrolling + }, + headingStyle: { + fontFamily: "inter", + fontWeight: "600", + fontSize: "16px", + color: "#121212", + width: "70%", + borderBottom: "1px solid black", + }, + }; + + const addToCart = (item) => { + // Check if the item is already in the cart + const isItemInCart = cartItem.find((cartItem) => cartItem._id === item._id); + + if (isItemInCart) { + // Item is already in the cart, show a confirmation message + swal("Item already in cart", "", "info"); + } else { + // Item is not in the cart, add it to the cart with quantity initialized to 1 + setCartItem([...cartItem, { ...item, quantity: 1 }]); + // Show a success message + swal("Item added to cart", "", "success"); + } + }; + + const handleIncrease = (index) => { + const newCart = [...cartItem]; + newCart[index].quantity += 1; + newCart[index].total_amount = + newCart[index].quantity * newCart[index].price + + newCart[index].gst_amount; // Recalculate total amount + setCartItem(newCart); + }; + + const handleDecrease = (index) => { + const newCart = [...cartItem]; + if (newCart[index].quantity > 1) { + newCart[index].quantity -= 1; + newCart[index].total_amount = + newCart[index].quantity * newCart[index].price + + newCart[index].gst_amount; // Recalculate total amount + setCartItem(newCart); + } + }; + + const removeCartItemHandler = (id) => { + console.log("id", id); + const newCart = cartItem.filter((item) => item._id !== id); + setCartItem(newCart); + }; + // Calculate subtotal of all items in cart + const calculateTotal = () => { + let subtotal = 0; + cartItem.forEach((item) => { + subtotal += item.total_amount; + }); + setTotal(subtotal); + }; + + useEffect(() => { + calculateTotal(); + }, [cartItem]); + console.log(user); + return ( +
+
+
+ {/* Part 1: Top Part */} +
+
+
+
+ {/* Customer search */} +
+ + Select Customer: + + setQuery(e.target.value)} + InputProps={{ + endAdornment: ( + handleSearchClick(query)} + > + + + ), + disableUnderline: true, + }} + /> +
+ {query !== "" && ( +
+ + + + + + + + + + {!loading && showData.length === 0 && ( + + + + )} + {loading ? ( + + + + ) : ( + showData.map((user, index) => ( + handleClick(user?._id)} + className="cursor-pointer hover:bg-gray-100" + > + + {/* + */} + + )) + )} + +
Customer NameAddressMobile No.
+
+ +
+
+ Loading... +
{user.name}{`${user?.street}, ${user?.city}, ${user?.state}, ${user?.country}, ${user?.postalCode}`}{`${user?.phone_Number}`}
+
+ )} + {/* Display selected customer */} + {currentUser && ( + // Display customer details +
+
+
+
+ + Customer Name: + + {`${currentUser?.first_Name} ${currentUser?.last_Name}`} +
+
+ + Mobile No.: + + {`${currentUser?.phone_Number}`} +
+
+ + Address: + + {`${currentUser?.street}, ${currentUser?.city}, ${currentUser?.state}, ${currentUser?.country}, ${currentUser?.postalCode}`} +
+
+
+
+ )} + {/* Sales Type radio buttons */} +
+ + Sales Type: + +
+
+ + +
+
+ + +
+
+
+
+
+
+
+ {/* Part 2: Panel 1 and Panel 2 */} +
+ {/* Panel 1 (Left Hand Side) */} +
+
+ {/* Category selection */} +
+ + Categories: + + + + +
+ {/* Product display */} +
+
+ + + + + + + + + + + {filteredItems.map((item, index) => ( + + + + + + + ))} + +
Product ImageProduct NamePriceAction
+ {item.image && item.image.length > 0 && ( + Product Image + )} + {item.name}{item.price} + +
+
+
+
+
+ {/* Panel 2 (Right Hand Side) */} +
+
+ {/* Display added products */} + + Added Products: + + {/* Display added products */} +
+ + + + + + + + + + Product + + + Quantity + + + Price + + + GST + + + + Subtotal + + + + + {cartItem.length === 0 ? ( + + + + Add products for shopping + + + + ) : ( + cartItem.map((row, index) => ( + + + {/* {row.product} */} + + + + + + + {row.name} + + + removeCartItemHandler(row._id) + } + sx={{ + color: "#6C7275", + width: "105%", + display: "flex", + alignItems: "center", + // justifyContent: "space-between", + cursor: "pointer", + ml: "10px", + + // border: 'solid' + }} + > + + + Remove + + + + + + + + + handleDecrease(index) + } + > + - + + + {row && row.quantity} + + handleIncrease(index) + } + > + + + + + + + ₹{row.price} + + + ₹{row?.gst_amount} + + + + {/* ${row.subtotal}${individualSubtotals[index]} */} + ₹{row.total_amount} + + + )) + )} + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Left side content */} +
+ {salesType === "" ? null : salesType === + "inStoreDelivery" ? ( +
+ {/* Display in-store delivery options */} + + In-Store delivery: + +
+ + +
+
+ + +
+ +
+ ) : ( +
+ {/* Display button for sending payment link */} + + +
+ )} +
+ + {/* Total Section */} +
+ + Total: + + + ₹{total} + +
+
+
+
+
+
+
+
+
+ ); +}; + +export default Pos;