From ae13816aa934eecc2b97e15796f08f64f72fad71 Mon Sep 17 00:00:00 2001 From: Sibunnayak Date: Tue, 16 Apr 2024 15:32:11 +0530 Subject: [PATCH 1/6] 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; From a7122792fa12613344220ab5c51b4b3649a6e9cf Mon Sep 17 00:00:00 2001 From: roshangarg Date: Fri, 26 Apr 2024 19:34:55 +0530 Subject: [PATCH 2/6] employee section ui is done --- src/_nav.js | 21 +- src/routes.js | 38 +- .../CustomerSupport/EmailCMS/EmailCms.js | 111 ++++ .../EmailCMS/RegistrationEmail.js | 207 ++++++++ src/views/EmployeeAccess/Employee.js | 479 ++++++++++++++++++ src/views/EmployeeAccess/addEmployee.js | 123 +++++ 6 files changed, 964 insertions(+), 15 deletions(-) create mode 100644 src/views/CustomerSupport/EmailCMS/EmailCms.js create mode 100644 src/views/CustomerSupport/EmailCMS/RegistrationEmail.js create mode 100644 src/views/EmployeeAccess/Employee.js create mode 100644 src/views/EmployeeAccess/addEmployee.js diff --git a/src/_nav.js b/src/_nav.js index 2e8ec6a..b0c36b0 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -24,6 +24,7 @@ import { cilUser, cilAlarm, cilFeaturedPlaylist, + cilLocationPin, } from "@coreui/icons"; import { CNavGroup, CNavItem, CNavTitle, CTabContent } from "@coreui/react"; @@ -40,12 +41,7 @@ const _nav = [ icon: , to: "/customers-details", }, - // { - // component: CNavItem, - // name: "Design", - // icon: , - // to: "/design", - // }, + { component: CNavGroup, name: "Charts", @@ -297,6 +293,12 @@ const _nav = [ icon: , to: "/contact/request", }, + // { + // component: CNavItem, + // name: "Email CMS", + // icon: , + // to: "/email-cms", + // }, ], }, //Blog start @@ -306,6 +308,13 @@ const _nav = [ icon: , to: "/blogs", }, + // Employee + { + component: CNavItem, + name: "Employee", + icon: , + to: "/employee", + }, // { // component: CNavGroup, diff --git a/src/routes.js b/src/routes.js index c30e161..11c89e1 100644 --- a/src/routes.js +++ b/src/routes.js @@ -137,6 +137,10 @@ import { element } from "prop-types"; import OrderdayChart from "./views/Charts/OrderDaywise"; import RevenueCharts from "./views/Charts/RevenueCharts"; import AddCustomer from "./views/customerDetails/addCustomer"; +import EmailCms from "./views/CustomerSupport/EmailCMS/EmailCms"; +import RegistrationEmail from "./views/CustomerSupport/EmailCMS/RegistrationEmail"; +import Employee from "./views/EmployeeAccess/Employee"; +import AddEmployee from "./views/EmployeeAccess/addEmployee"; const routes = [ { path: "/", exact: true, name: "Home" }, { @@ -275,6 +279,16 @@ const routes = [ element: AddContactRequest, }, //Support Requests + // { + // path: "/email-cms", + // name: "CustomerSupport Requests", + // element: EmailCms, + // }, + // { + // path: "/email-cms/registration-email", + // name: "CustomerSupport Requests", + // element: RegistrationEmail, + // }, { path: "/support/request", @@ -334,17 +348,17 @@ const routes = [ path: "/home", name: "Home", element: Home, - }, + }, { path: "/home/panel-1", name: "EditPanel1", element: EditPanel1, - }, + }, { path: "/home/panel-2", name: "EditPanel2", element: EditPanel2, - }, + }, { path: "/home/panel-3", name: "EditPanel3", @@ -354,12 +368,7 @@ const routes = [ path: "/home/panel-4", name: "EditPanel4", element: Editpanel4, - }, - - - - - + }, // { path: '/complaint/view/:id', name: 'view Complain', element: ViewComplaint }, //Complaints @@ -568,6 +577,17 @@ const routes = [ name: "Blogs", element: ViewBlog, }, + // Employee + { + path: "/employee", + name: "Employee", + element: Employee, + }, + { + path: "/add-employee", + name: "Employee", + element: AddEmployee, + }, //Charts { path: "/new-user-day-wise", diff --git a/src/views/CustomerSupport/EmailCMS/EmailCms.js b/src/views/CustomerSupport/EmailCMS/EmailCms.js new file mode 100644 index 0000000..dfb2489 --- /dev/null +++ b/src/views/CustomerSupport/EmailCMS/EmailCms.js @@ -0,0 +1,111 @@ +import { + Button, + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Typography, +} from "@mui/material"; +import React from "react"; +import { Link } from "react-router-dom"; + +export default function EmailCms() { + const pages = [ + { + name: "New user registration", + action: "Edit", + path: "/email-cms/registration-email", + }, + { + name: "Forgot Password", + action: "Edit", + path: "#", + }, + { + name: "Change Password Notification ", + action: "Edit", + path: "#", + }, + { + name: "New Order", + action: "Edit", + path: "#", + }, + { + name: "Order - Processing", + action: "Edit", + path: "#", + }, + { + name: "Order - Dispatched", + action: "Edit", + path: "#", + }, + { + name: "Order - Delivered", + action: "Edit", + path: "#", + }, + { + name: "Order - Cancelled", + action: "Edit", + path: "#", + }, + ]; + + return ( +
+ + Email CMS + + + + + + Page + + Action + + + + + {pages.map((row) => ( + + + {row.name} + + + {" "} + + + + + + ))} + +
+
+
+ ); +} diff --git a/src/views/CustomerSupport/EmailCMS/RegistrationEmail.js b/src/views/CustomerSupport/EmailCMS/RegistrationEmail.js new file mode 100644 index 0000000..2f274f3 --- /dev/null +++ b/src/views/CustomerSupport/EmailCMS/RegistrationEmail.js @@ -0,0 +1,207 @@ +import { Typography } from "@material-ui/core"; +import { Box, Button } from "@mui/material"; + +import React, { useEffect, useState } from "react"; +import ReactrichTextEditor from "../../Content/reactrichTextEditor"; +import ReactQuill from "react-quill"; +import "react-quill/dist/quill.snow.css"; +import axios from "axios"; +import { isAutheticated } from "src/auth"; +import { useNavigate, useNavigation } from "react-router-dom"; + +// const TOOLBAR_OPTIONS = [ +// [{ header: [1, 2, 3, 4, 5, 6, false] }], +// [{ font: [] }], +// [{ list: "ordered" }, { list: "bullet" }], +// ["bold", "italic", "underline", "strike"], +// [{ color: [] }, { background: [] }], +// [{ align: [] }], +// [{ script: "super" }, { script: "sub" }], +// ["undo", "redo"], +// ]; + +export default function RegistrationEmail() { + const [title, setTitle] = useState("Registration Email"); + const [welcomemsg, setWelcomeMsg] = useState(""); + const [welcomemsgforDescription, setWelcomeMsgForDescription] = useState(""); + + const [subject, setSubject] = useState(""); + const [description, setDescription] = useState(""); + const [content, setContent] = useState(""); + const [added, setAdded] = useState(false); + const [olderContent, setOlderContent] = useState(""); + const [id, setId] = useState(null); + + const token = isAutheticated(); + + const getTermsAndConditions = async () => { + const response = await axios.get("/api/get-email-data", { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + if (response.status === 200) { + if (response.data?.registerEmaildata.length === 0) { + return; + } + // console.log(response); + // setContent(response?.data?.registerEmaildata[0]?.termsAndContionContent); + // setOlderContent( + // response?.data?.registerEmaildata[0]?.termsAndContionContent + // ); + setSubject(response?.data?.registerEmaildata[0]?.subject); + setDescription(response?.data?.registerEmaildata[0]?.description); + setId(response?.data?.registerEmaildata[0]?._id); + } + }; + + const addTermsandConditions = async () => { + const response = await axios.post( + "/api/register-email", + { subject: subject, description: description }, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ); + if (response.status == 200) { + swal({ + title: "Congratulations!!", + text: response?.data?.message, + icon: "success", + button: "OK", + }); + } + }; + const handleCancelClick = () => { + setAdded(!added); + }; + + const handleSaveClick = async () => { + // if (id === null) { + await addTermsandConditions(); + setAdded(true); + // } else { + // await updateContent(); + // setAdded(false); + // } + + // Reload terms and conditions + // await getTermsAndConditions(); + }; + useEffect(() => { + // addTermsandConditions(); + getTermsAndConditions(); + }, [added]); + return ( +
+
+ + +
+ + + {/* setTitle(e.target.value)} + variant="outlined" + size="small" + fullWidth + /> */} + + {" "} + Email Confiramtion:{" "} + + +
+ + + setWelcomeMsg(e.target.value)} + /> +
+ App Name : Smellika +
+ + + + setSubject(e.target.value)} + /> +
+ +
+ + + setWelcomeMsgForDescription(e.target.value)} + /> + + +
+
+
+ ); +} diff --git a/src/views/EmployeeAccess/Employee.js b/src/views/EmployeeAccess/Employee.js new file mode 100644 index 0000000..c1b20b4 --- /dev/null +++ b/src/views/EmployeeAccess/Employee.js @@ -0,0 +1,479 @@ +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, +} from "@mui/material"; +import SearchIcon from "@mui/icons-material/Search"; +import Fuse from "fuse.js"; +import { Typography } from "@material-ui/core"; +// import OrderDetails from "./orderDetails"; +const Employee = () => { + const token = isAutheticated(); + const [query, setQuery] = useState(""); + const navigate = useNavigate(); + const [loading, setLoading] = useState(true); + const [loading1, setLoading1] = useState(true); + const [success, setSuccess] = useState(true); + const [users, setUsers] = useState([]); + + const [currentPage, setCurrentPage] = useState(1); + const [itemPerPage, setItemPerPage] = useState(10); + const [showData, setShowData] = useState(users); + + const handleShowEntries = (e) => { + setCurrentPage(1); + setItemPerPage(e.target.value); + }; + + // const getUsers = async () => { + // axios + // .get(`/api/v1/admin/users`, { + // headers: { + // Authorization: `Bearer ${token}`, + // }, + // }) + // .then((res) => { + // setUsers(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); + // }); + // }; + + // useEffect(() => { + // getUsers(); + // }, [success]); + // console.log(users); + + // useEffect(() => { + // const loadData = () => { + // const indexOfLastPost = currentPage * itemPerPage; + // const indexOfFirstPost = indexOfLastPost - itemPerPage; + // setShowData(users.slice(indexOfFirstPost, indexOfLastPost)); + // }; + // loadData(); + // }, [currentPage, itemPerPage, users]); + // console.log(users); + + // const handleDelete = (id) => { + // swal({ + // title: "Are you sure?", + // icon: "error", + // buttons: { + // Yes: { text: "Yes", value: true }, + // Cancel: { text: "Cancel", value: "cancel" }, + // }, + // }).then((value) => { + // if (value === true) { + // axios + // .delete(`/api/user-address/deleteAddress/${id}`, { + // headers: { + // "Access-Control-Allow-Origin": "*", + // Authorization: `Bearer ${token}`, + // }, + // }) + // .then((res) => { + // swal({ + // title: "Deleted", + // text: "Address Deleted successfully!", + // icon: "success", + // button: "ok", + // }); + // setSuccess((prev) => !prev); + // }) + // .catch((err) => { + // swal({ + // title: "Warning", + // text: "Something went wrong!", + // icon: "error", + // button: "Retry", + // dangerMode: true, + // }); + // }); + // } + // }); + // }; + + return ( +
+
+
+
+
+
+
+ All Employees +
+ +
+ +
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+ +
+ + + + + + + + + + + + + {!loading && showData.length === 0 && ( + + + + )} + {!loading ? ( + + + + ) : ( + // showData.map((user, i) => { + // return ( + // + // + // + + // + // {loading1 && ( + // <> + // + // + // + // )} + + // + + // + // + // ); + // }) + + + + {/* */} + + + {/* + */} + + + )} + +
Employee NameEmailAccess to Action
+
No Data Available
+
+ Loading... +
{user.name}{user._id} + // {new Date(user.createdAt).toLocaleString( + // "en-IN", + // { + // weekday: "short", + // month: "short", + // day: "numeric", + // year: "numeric", + // hour: "numeric", + // minute: "numeric", + // hour12: true, + // } + // )} + // loading...loading... + // {/* + // + // + // + // + // + // + // + // */} + // + // + // + //
Roshan Gargroshan@gmail.comProfile ImagedashboardLast PurchaseOrders + + +
+
+ +
+
+
+ Showing {currentPage * itemPerPage - itemPerPage + 1} to{" "} + {Math.min(currentPage * itemPerPage, users.length)} of{" "} + {users.length} entries +
+
+ +
+
+
    +
  • + setCurrentPage((prev) => prev - 1)} + > + Previous + +
  • + + {!(currentPage - 1 < 1) && ( +
  • + + setCurrentPage((prev) => prev - 1) + } + > + {currentPage - 1} + +
  • + )} + +
  • + + {currentPage} + +
  • + + {!( + (currentPage + 1) * itemPerPage - itemPerPage > + users.length - 1 + ) && ( +
  • + { + setCurrentPage((prev) => prev + 1); + }} + > + {currentPage + 1} + +
  • + )} + +
  • + users.length - 1 + ) + ? "paginate_button page-item next" + : "paginate_button page-item next disabled" + } + > + setCurrentPage((prev) => prev + 1)} + > + Next + +
  • +
+
+
+
+
+
+
+
+
+
+
+ ); +}; + +export default Employee; diff --git a/src/views/EmployeeAccess/addEmployee.js b/src/views/EmployeeAccess/addEmployee.js new file mode 100644 index 0000000..b0efd0d --- /dev/null +++ b/src/views/EmployeeAccess/addEmployee.js @@ -0,0 +1,123 @@ +import { Box, Button, Typography } from "@mui/material"; +import React, { useState } from "react"; +import FormGroup from "@mui/material/FormGroup"; +import FormControlLabel from "@mui/material/FormControlLabel"; +import Checkbox from "@mui/material/Checkbox"; +import { useNavigate } from "react-router-dom"; +import _nav from "src/_nav"; + +const AddEmployee = () => { + const [employeeName, setEmployeeName] = useState(""); + const [email, setEmail] = useState(""); + const navigate = useNavigate(); + const [checkedItems, setCheckedItems] = useState({}); + const filteredNav = _nav.filter((item) => item.name !== "Employee"); + const handleCheckboxChange = (name) => (event) => { + setCheckedItems({ + ...checkedItems, + [name]: event.target.checked, + }); + }; + console.log(checkedItems); + + return ( +
+ + {/* setTitle(e.target.value)} + variant="outlined" + size="small" + fullWidth + /> */} + + {" "} + Add Employee:{" "} + + +
+ + + setEmployeeName(e.target.value)} + /> +
+ +
+ + + setEmail(e.target.value)} + /> +
+ + +
+ {filteredNav.map((item, index) => ( +
+ + {item.name} +
+ ))} +
+
+
+ + +
+
+
+ ); +}; + +export default AddEmployee; From 0277bbe888034b7e7d864d9dc8f297174b8ce379 Mon Sep 17 00:00:00 2001 From: Sibunnayak Date: Sun, 28 Apr 2024 17:25:03 +0530 Subject: [PATCH 3/6] point of sale complete with QrCode and Cash --- package.json | 1 + public/index.html | 67 +- src/_nav.js | 12 + src/index.js | 2 +- src/routes.js | 7 + .../PointOfSale/AddressSelectionModal.js | 77 ++ src/views/PointOfSale/Pos.js | 861 +++++++++++----- src/views/orders/InStoreCashOrders.js | 386 +++++++ src/views/orders/InStoreQRCodeOrders.js | 386 +++++++ src/views/orders/NewOrders.js | 7 +- src/views/orders/POSViewOrders.js | 946 ++++++++++++++++++ 11 files changed, 2448 insertions(+), 304 deletions(-) create mode 100644 src/views/PointOfSale/AddressSelectionModal.js create mode 100644 src/views/orders/InStoreCashOrders.js create mode 100644 src/views/orders/InStoreQRCodeOrders.js create mode 100644 src/views/orders/POSViewOrders.js diff --git a/package.json b/package.json index 497456f..18a472f 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "react-dom": "^18.0.0", "react-draft-wysiwyg": "^1.15.0", "react-hot-toast": "^2.4.0", + "react-modal": "^3.16.1", "react-qr-code": "^2.0.11", "react-quill": "^2.0.0", "react-redux": "^7.2.9", diff --git a/public/index.html b/public/index.html index 1d602d2..ca6a3bf 100644 --- a/public/index.html +++ b/public/index.html @@ -7,37 +7,26 @@ * License MIT --> - - - - - - - - Smellika Admin - - - - - + + + + - - + - + - - - + + + - - -
- - - - + + + + + \ No newline at end of file diff --git a/src/_nav.js b/src/_nav.js index fbf0b81..49d2855 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -156,6 +156,18 @@ const _nav = [ icon: , to: "/orders/cancelled", }, + { + component: CNavItem, + name: "In Store Cash Orders", + icon: , + to: "/inStoreCashOrders/new", + }, + { + component: CNavItem, + name: "In Store QRCode Orders", + icon: , + to: "/InStoreQRCodeOrders/new", + }, ], }, { diff --git a/src/index.js b/src/index.js index 466639c..3e4516a 100644 --- a/src/index.js +++ b/src/index.js @@ -14,7 +14,7 @@ import { cibGmail } from "@coreui/icons"; import { createRoot } from "react-dom/client"; const setupAxios = () => { - //axios.defaults.baseURL = "http://localhost:5000"; + // axios.defaults.baseURL = "http://localhost:5000"; axios.defaults.baseURL = "https://api.smellika.com"; axios.defaults.headers = { diff --git a/src/routes.js b/src/routes.js index 6393b6c..34f7de9 100644 --- a/src/routes.js +++ b/src/routes.js @@ -138,6 +138,9 @@ import OrderdayChart from "./views/Charts/OrderDaywise"; import RevenueCharts from "./views/Charts/RevenueCharts"; import AddCustomer from "./views/customerDetails/addCustomer"; import Pos from "./views/PointOfSale/Pos"; +import InStoreCashOrders from "./views/orders/InStoreCashOrders"; +import POSViewOrders from "./views/orders/POSViewOrders"; +import InStoreQRCodeOrders from "./views/orders/InStoreQRCodeOrders"; const routes = [ { path: "/", exact: true, name: "Home" }, { @@ -445,6 +448,10 @@ const routes = [ name: "Returned Orders", element: ReturnedOrders, }, + //Point of sale orders + { path: "/inStoreCashOrders/new", name: "In Store Cash Orders", element:InStoreCashOrders }, + { path: "/InStoreQRCodeOrders/new", name: "In Store QR Code Orders", element:InStoreQRCodeOrders }, + { path: "/inStoreOrders/:status/:id", name: "View In Store Cash Orders", element: POSViewOrders }, // { path: "/order/:status/:id", name: "View Order", element: ViewOdr }, //dashboard diff --git a/src/views/PointOfSale/AddressSelectionModal.js b/src/views/PointOfSale/AddressSelectionModal.js new file mode 100644 index 0000000..32cf183 --- /dev/null +++ b/src/views/PointOfSale/AddressSelectionModal.js @@ -0,0 +1,77 @@ +import React from "react"; +import Modal from "react-modal"; + +const AddressSelectionModal = ({ isOpen, onClose, addresses, onSelect }) => { + const modalStyle = { + overlay: { + backgroundColor: "rgba(0, 0, 0, 0.5)", + }, + content: { + top: "50%", + left: "50%", + right: "auto", + bottom: "auto", + marginRight: "-50%", + transform: "translate(-50%, -50%)", + maxWidth: "800px", + width: "90%", + }, + }; + + const tableStyle = { + width: "100%", + borderCollapse: "collapse", + }; + + const thTdStyle = { + border: "1px solid #ddd", + padding: "8px", + }; + + const thStyle = { + ...thTdStyle, + backgroundColor: "#f2f2f2", + }; +// console.log(addresses); + return ( + +

Select Address

+ + + + + + + + + + + {/* Add additional columns as needed */} + + + + {addresses.map((address, index) => ( + onSelect(address)} + style={{ cursor: "pointer", ...thTdStyle }} + > + + + + + + + + {/* Add additional columns as needed */} + + ))} + +
First NameLast NamePhone NumberStreetCityPostal CodeState
{address.first_Name}{address.last_Name}{address.phone_Number}{address.street}{address.city}{address.postalCode}{address.state}
+ +
+ ); +}; + +export default AddressSelectionModal; + diff --git a/src/views/PointOfSale/Pos.js b/src/views/PointOfSale/Pos.js index 1aaaf5f..3ed84b2 100644 --- a/src/views/PointOfSale/Pos.js +++ b/src/views/PointOfSale/Pos.js @@ -18,7 +18,7 @@ import { Paper, Typography, } from "@mui/material"; - +import toast, { Toaster } from "react-hot-toast"; import SearchIcon from "@mui/icons-material/Search"; import ClearIcon from "@mui/icons-material/Clear"; // import PercentIcon from "@mui/icons-material/Percent"; @@ -28,96 +28,63 @@ import TableCell from "@mui/material/TableCell"; import TableContainer from "@mui/material/TableContainer"; import TableHead from "@mui/material/TableHead"; import TableRow from "@mui/material/TableRow"; +import AddressSelectionModal from "./AddressSelectionModal"; 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`, { + + const [usersWithAddresses, setUsersWithAddresses] = useState([]); + + const getUsersWithAddresses = async () => { + try { + const usersResponse = await 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 users = usersResponse.data.users; + + const usersWithAddressesPromises = users.map(async (user) => { + try { + const addressResponse = await axios.get( + `/api/shipping/address/user/address/${user._id}`, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ); + const userWithAddress = { + ...user, + address: addressResponse.data?.UserShippingAddress || [], + }; + return userWithAddress; + } catch (error) { + throw new Error(`Error fetching address for user ${user._id}`); + } + }); + + const usersWithAddresses = await Promise.all(usersWithAddressesPromises); + setUsersWithAddresses(usersWithAddresses); + } catch (error) { + swal({ + title: error, + text: "Please login to access the resource or refresh the page.", + icon: "error", + button: "Retry", + dangerMode: true, + }); + } }; - const [showData, setShowData] = useState(user); + + useEffect(() => { + getUsersWithAddresses(); + }, [token]); + const [showData, setShowData] = useState(usersWithAddresses); const [currentUser, setCurrentUser] = useState(null); - const [salesType, setSalesType] = useState(""); const [storedelivery, setStoreDelivery] = useState(""); // Function to handle change in radio button selection @@ -133,23 +100,19 @@ const Pos = () => { setCurrentUser(null); const lowerCaseQuery = query.toLowerCase(); // Convert query to lowercase - const searchedResult = user.filter((item) => + const searchedResult = usersWithAddresses.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); + const customer = usersWithAddresses.find((user) => user._id === id); setCurrentUser(customer); }; @@ -165,7 +128,7 @@ const Pos = () => { const getAllProducts = async () => { try { - const response = await axios.get("/api/product/getAll/"); + const response = await axios.get("/api/product/getAll/user/"); if (response.status === 200) { // setProductData(response?.data?.product); const activeProducts = response?.data?.product.filter( @@ -254,15 +217,49 @@ const Pos = () => { }; const addToCart = (item) => { - // Check if the item is already in the cart - const isItemInCart = cartItem.find((cartItem) => cartItem._id === item._id); + // Check if the item is already in the cart with the same product ID and variant + const existingCartItemIndex = cartItem.findIndex( + (cartItem) => + cartItem.product._id === item._id && + cartItem.variant._id === selectedVariants[item._id]?._id + ); - if (isItemInCart) { - // Item is already in the cart, show a confirmation message - swal("Item already in cart", "", "info"); + if (existingCartItemIndex !== -1) { + // Item with the same product ID and variant already exists in the cart, update its quantity + const newCart = [...cartItem]; + const existingCartItem = newCart[existingCartItemIndex]; + const selectedVariant = selectedVariants[item._id]; + const price = selectedVariant ? selectedVariant.price : item.price; + + existingCartItem.quantity += 1; + existingCartItem.subtotal += + parseFloat(price) + parseFloat(item.gst_amount); + + setCartItem(newCart); + // Show a success message + swal("Item quantity updated in cart", "", "success"); } else { - // Item is not in the cart, add it to the cart with quantity initialized to 1 - setCartItem([...cartItem, { ...item, quantity: 1 }]); + // Item is not in the cart, add it + const selectedVariant = selectedVariants[item._id]; + const price = selectedVariant ? selectedVariant.price : item.price; + const totalAmount = parseFloat(price) + parseFloat(item.gst_amount); + + setCartItem([ + ...cartItem, + { + product: item, + quantity: 1, + variant: { + _id: selectedVariant?._id, + gst_Id: selectedVariant?.gst_Id, + price: selectedVariant?.price, + volume: selectedVariant?.volume, + weight: selectedVariant?.weight, + variant_Name: selectedVariant?.variant_Name, + }, + subtotal: totalAmount, + }, + ]); // Show a success message swal("Item added to cart", "", "success"); } @@ -270,34 +267,53 @@ const Pos = () => { const handleIncrease = (index) => { const newCart = [...cartItem]; + const item = newCart[index]; + + const selectedVariant = selectedVariants[item.product._id]; + const price = selectedVariant ? selectedVariant.price : item.product.price; + const totalAmount = + (item.quantity + 1) * parseFloat(price) + + parseFloat(item.product.gst_amount); + newCart[index].quantity += 1; - newCart[index].total_amount = - newCart[index].quantity * newCart[index].price + - newCart[index].gst_amount; // Recalculate total amount + newCart[index].subtotal = totalAmount; + setCartItem(newCart); }; const handleDecrease = (index) => { const newCart = [...cartItem]; - if (newCart[index].quantity > 1) { + const item = newCart[index]; + + if (item.quantity > 1) { + const selectedVariant = selectedVariants[item.product._id]; + const price = selectedVariant + ? selectedVariant.price + : item.product.price; + const totalAmount = + (item.quantity - 1) * parseFloat(price) + + parseFloat(item.product.gst_amount); + newCart[index].quantity -= 1; - newCart[index].total_amount = - newCart[index].quantity * newCart[index].price + - newCart[index].gst_amount; // Recalculate total amount + newCart[index].subtotal = totalAmount; + setCartItem(newCart); } }; - const removeCartItemHandler = (id) => { - console.log("id", id); - const newCart = cartItem.filter((item) => item._id !== id); + // console.log(cartItem) + const removeCartItemHandler = (id, variant) => { + const newCart = cartItem.filter( + (item) => item?.product._id !== id || item.variant._id !== variant + ); setCartItem(newCart); }; + // Calculate subtotal of all items in cart const calculateTotal = () => { let subtotal = 0; cartItem.forEach((item) => { - subtotal += item.total_amount; + subtotal += item.subtotal; }); setTotal(subtotal); }; @@ -305,7 +321,274 @@ const Pos = () => { useEffect(() => { calculateTotal(); }, [cartItem]); - console.log(user); + // console.log(usersWithAddresses); + const [showChangeAddress, setShowChangeAddress] = useState(false); + const [selectedAddress, setSelectedAddress] = useState( + currentUser?.address[0] + ); + useEffect(() => { + setSelectedAddress(currentUser?.address[0]); + }, [currentUser]); + const handleChangeAddress = () => { + setShowChangeAddress(true); + }; + + const handleSelectAddress = (address) => { + setSelectedAddress(address); + setShowChangeAddress(false); + }; + + // const checkoutCash = async () => { + // // console.log("Checkout button clicked"); + // try { + // const config = { + // headers: { + // Authorization: `Bearer ${token}`, + // }, + // }; + // const cartData = cartItem.map((item) => ({ + // product: item.product, // Entire product object + // quantity: item.quantity, + // variant: item.variant, // Entire variant object + // subtotal: item.subtotal, + // })); + // const order = { + // userr: currentUser._id, + // address: selectedAddress._id, + // cart: cartData, + // subtotal: total, + // orderType: "PointOfSale", + // }; + + // // Send POST request to backend API endpoint + // const response = await axios.post( + // "/api/order/pos-checkout/", + // order, + // config + // ); + + // toast.success("Order Placed! Your order has been successfully placed."); + // swal({ + // title: "Order Placed!", + // text: `Order ID: ${ + // response.data.order.orderID + // }\nDate and Time: ${new Date( + // response.data.order.createdAt + // ).toLocaleString("en-IN", { + // month: "short", + // day: "numeric", + // year: "numeric", + // hour: "2-digit", + // minute: "numeric", + // hour12: true, + // })}`, + // icon: "success", + // button: "OK", + // }); + + // // Clear cart items, reset current user and address, and reset radio button states + // setCartItem([]); + // setCurrentUser(null); + // setSelectedAddress(null); + // setSalesType(""); + // setStoreDelivery(""); + // setTotal(0); + // setCategoryValue("All"); + // } catch (error) { + // // Handle errors + // console.error("Error placing order:", error); + + // toast.error( + // "Error! There was an error placing your order. Please try again later." + // ); + // } + // }; + const checkoutCash = async () => { + const config = { + headers: { + Authorization: `Bearer ${token}`, + }, + }; + + const cartData = cartItem.map((item) => ({ + product: item.product, // Entire product object + quantity: item.quantity, + variant: item.variant, // Entire variant object + subtotal: item.subtotal, + })); + + const order = { + userr: currentUser._id, + address: selectedAddress._id, + cart: cartData, + subtotal: total, + orderType: "PointOfSale", + }; + + // Send POST request to backend API endpoint + axios + .post("/api/order/pos-checkout/", order, config) + .then((response) => { + // Handle successful response + swal({ + title: "Order Placed!", + text: `Order ID: ${ + response.data.order.orderID + }\nDate and Time: ${new Date( + response.data.order.createdAt + ).toLocaleString("en-IN", { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + })}`, + icon: "success", + button: "OK", + }); + + // Clear cart items, reset current user and address, and reset radio button states + setCartItem([]); + setCurrentUser(null); + setSelectedAddress(null); + setStoreDelivery(""); + setTotal(0); + setCategoryValue("All"); + }) + .catch((error) => { + // Handle errors + console.error("Error placing order:", error); + + toast.error( + "Error! There was an error placing your order. Please try again later." + ); + }); + }; + + // for QR Code + const checkoutQRCode = async () => { + try { + const { + data: { key }, + } = await axios.get( + `/api/order/getRzpKey/${currentUser.name}/${currentUser.email}`, + { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + } + ); + + const cartData = cartItem.map((item) => ({ + product: item.product, // Entire product object + quantity: item.quantity, + variant: item.variant, // Entire variant object + subtotal: item.subtotal, + })); + + const { + data: { order }, + } = await axios.post( + "/api/order/Rzpcheckout", + { + userr: currentUser._id, + address: selectedAddress._id, + cart: cartData, + subtotal: total, + orderType: "PointOfSale", + }, + { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + } + ); + + const options = { + key, + amount: order.amount, + currency: "INR", + name: "Smellika", + description: "Smellika RazorPay", + image: + "https://res.cloudinary.com/dnmgivd1x/image/upload/v1707058241/bolo/Logo/aasy4ulmbbtqmcxi64j0.jpg", + order_id: order.id, + // callback_url: + // "http://localhost:5000/api/order/pos-paymentverification/", + callback_url: + "https://api.smellika.com/api/order/pos-paymentverification/", + + prefill: { + name: currentUser.name, + email: currentUser.email, + }, + notes: { + address: "Razorpay Corporate Office", + }, + theme: { + color: "#121212", + }, + }; + + const razor = new window.Razorpay(options); + + razor.on("payment.success", async function (response) { + // Handle successful payment + console.log("Payment successful:", response); + }); + + razor.open(); + } catch (error) { + if ( + error.response && + error.response.data && + error.response.data.message + ) { + // If error.response and its properties exist, handle the error message + toast.error(error.response.data.message); + } else { + // If error.response or its properties are undefined, handle the error generically + toast.error("An error occurred. Please try again later."); + } + } + }; + // varient + const [selectedVariants, setSelectedVariants] = useState({}); + + // Function to set default variant for each product + const setDefaultVariants = () => { + const defaultVariants = {}; + filteredItems.forEach((item) => { + defaultVariants[item._id] = + item.variants && item.variants.length > 0 ? item.variants[0] : null; + }); + setSelectedVariants(defaultVariants); + }; + + // Function to handle variant change + const handleVariantChange = (productId, event) => { + const selectedVariantName = event.target.value; + const selectedVariant = filteredItems + .find((item) => item._id === productId) + ?.variants.find( + (variant) => variant.variant_Name === selectedVariantName + ); + setSelectedVariants((prevState) => ({ + ...prevState, + [productId]: selectedVariant, + })); + }; + // console.log(selectedVariants); + // console.log(cartItem); + // Call setDefaultVariants when the component mounts + useEffect(() => { + setDefaultVariants(); + }, [filteredItems]); + + // console.log("currentUser", currentUser); return (
@@ -403,7 +686,7 @@ const Pos = () => { textTransform: "capitalize", }} onClick={() => { - navigate("/pos/new-customer", { + navigate("/add-customer", { replace: true, }); }} @@ -424,12 +707,32 @@ const Pos = () => { showData.map((user, index) => ( handleClick(user?._id)} - className="cursor-pointer hover:bg-gray-100" + onClick={() => { + if (user.address.length === 0) { + toast.error( + "Please add an address for shopping." + ); + } else { + handleClick(user?._id); + } + }} + className={`cursor-pointer hover:bg-gray-100 ${ + user.address.length === 0 ? "opacity-50" : "" + }`} > {user.name} - {/* {`${user?.street}, ${user?.city}, ${user?.state}, ${user?.country}, ${user?.postalCode}`} - {`${user?.phone_Number}`} */} + {user.address.length === 0 ? ( + + Add address for shopping + + ) : ( + <> + + {`${user?.address[0]?.street}, ${user?.address[0]?.city}, ${user?.address[0]?.state}, ${user?.address[0]?.country}, ${user?.address[0]?.postalCode}`} + + {`${user?.address[0]?.phone_Number}`} + + )} )) )} @@ -438,101 +741,69 @@ const Pos = () => {
)} {/* Display selected customer */} - {currentUser && ( - // Display customer details -
-
-
-
- + {currentUser && ( +
+
+
+
+ + Customer Name: + + {`${currentUser?.name}`} +
+
+ + Mobile No.: + + {`${selectedAddress?.phone_Number}`} +
+
+ + Address: + + {`${selectedAddress?.street}, ${selectedAddress?.city}, ${selectedAddress?.state}, ${selectedAddress?.country}, ${selectedAddress?.postalCode}`} +
+
-
- - Mobile No.: - - {`${currentUser?.phone_Number}`} -
-
- - Address: - - {`${currentUser?.street}, ${currentUser?.city}, ${currentUser?.state}, ${currentUser?.country}, ${currentUser?.postalCode}`} + Change Address +
-
- )} - {/* Sales Type radio buttons */} -
- - Sales Type: - -
-
- - -
-
- - -
-
+ )} + {/* Render AddressSelectionModal only when currentUser exists */} + {currentUser && ( + setShowChangeAddress(false)} + addresses={currentUser.address} + onSelect={handleSelectAddress} + /> + )}
@@ -601,6 +872,7 @@ const Pos = () => { Product Image Product Name + variant Price Action @@ -618,7 +890,50 @@ const Pos = () => { )} {item.name} - {item.price} + + {item.variants && item.variants.length > 0 ? ( + + + + ) : ( + "No Variant" + )} + + + + {selectedVariants[item._id] + ? selectedVariants[item._id].price + : item.price} + -
- ) : ( + )} +
+ {/* ) : (
- {/* Display button for sending payment link */} - - + {salesType === "shipToCustomer" && ( + + )} + {salesType !== "shipToCustomer" && ( + + )}
- )} + )} */} {/* Total Section */} diff --git a/src/views/orders/InStoreCashOrders.js b/src/views/orders/InStoreCashOrders.js new file mode 100644 index 0000000..7cd0221 --- /dev/null +++ b/src/views/orders/InStoreCashOrders.js @@ -0,0 +1,386 @@ +import React, { useState, useEffect } from "react"; +import { Link } from "react-router-dom"; +import axios from "axios"; + +import { isAutheticated } from "src/auth"; +import Button from "@material-ui/core/Button"; + +function InStoreCashOrders() { + const token = isAutheticated(); + const [loading, setLoading] = useState(true); + const [success, setSuccess] = useState(true); + const [newOrdersData, setNewOrdersData] = useState([]); + console.log(newOrdersData); + + const [currentPage, setCurrentPage] = useState(1); + const [itemPerPage, setItemPerPage] = useState(10); + const [showData, setShowData] = useState(newOrdersData); + + const handleShowEntries = (e) => { + setCurrentPage(1); + setItemPerPage(e.target.value); + }; + + useEffect(() => { + function getNewOrder() { + axios + .get(`/api/order/getAll/new`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + const filteredOrders = res.data.order.filter( + (order) => order.orderType === "PointOfSale" && order.paymentMode === "cod" + ); + + // Set the filtered orders data + setNewOrdersData(filteredOrders); + setLoading(false); + }) + .catch((err) => { + console.log(err); + setLoading(false); + }); + } + getNewOrder(); + }, [success]); + + + useEffect(() => { + const loadData = () => { + const indexOfLastPost = currentPage * itemPerPage; + const indexOfFirstPost = indexOfLastPost - itemPerPage; + setShowData(newOrdersData.slice(indexOfFirstPost, indexOfLastPost)); + }; + loadData(); + }, [currentPage, itemPerPage, newOrdersData]); + + const handleDelete = (id) => { + console.log(id); + swal({ + title: "Are you sure?", + icon: "error", + buttons: { + Yes: { text: "Yes", value: true }, + Cancel: { text: "Cancel", value: "cancel" }, + }, + }).then((value) => { + if (value === true) { + axios + .delete(`/api/order/delete/${id}`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + setSuccess((prev) => !prev); + }) + .catch((err) => { + swal({ + title: "Warning", + text: err.response.data.message + ? err.response.data.message + : "Something went wrong!", + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + } + }); + }; + + return ( +
+
+
+
+
+
+
+ New Orders +
+ + {/*
+ + + +
*/} +
+
+
+
+
+
+
+
+
+
+ +
+
+
+ +
+ + + + + + + + + + + + + {!loading && showData.length === 0 && ( + + + + )} + {loading ? ( + + + + ) : ( + showData.map((order, i) => { + return ( + + + + + + + + + ); + }) + )} + +
Order IDCustomerOrder valueOrder AtStatusActions
+
No Data Available
+
+ Loading... +
{order?.orderID} + {order?.user?.name} + + ₹{order?.total_amount} + + {new Date(order?.createdAt).toLocaleString( + "en-IN", + { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + } + )} + + + {order?.orderStatus} + + + {/* */} + + + + {/* + + */} + + {/* */} +
+
+ +
+
+
+ Showing {currentPage * itemPerPage - itemPerPage + 1} to{" "} + {Math.min( + currentPage * itemPerPage, + newOrdersData.length + )}{" "} + of {newOrdersData.length} entries +
+
+ +
+
+
    +
  • + setCurrentPage((prev) => prev - 1)} + > + Previous + +
  • + + {!(currentPage - 1 < 1) && ( +
  • + + setCurrentPage((prev) => prev - 1) + } + > + {currentPage - 1} + +
  • + )} + +
  • + + {currentPage} + +
  • + + {!( + (currentPage + 1) * itemPerPage - itemPerPage > + newOrdersData.length - 1 + ) && ( +
  • + { + setCurrentPage((prev) => prev + 1); + }} + > + {currentPage + 1} + +
  • + )} + +
  • + newOrdersData.length - 1 + ) + ? "paginate_button page-item next" + : "paginate_button page-item next disabled" + } + > + setCurrentPage((prev) => prev + 1)} + > + Next + +
  • +
+
+
+
+
+
+
+
+
+
+
+ ); +} + +export default InStoreCashOrders; diff --git a/src/views/orders/InStoreQRCodeOrders.js b/src/views/orders/InStoreQRCodeOrders.js new file mode 100644 index 0000000..1892060 --- /dev/null +++ b/src/views/orders/InStoreQRCodeOrders.js @@ -0,0 +1,386 @@ +import React, { useState, useEffect } from "react"; +import { Link } from "react-router-dom"; +import axios from "axios"; + +import { isAutheticated } from "src/auth"; +import Button from "@material-ui/core/Button"; + +function InStoreQRCodeOrders() { + const token = isAutheticated(); + const [loading, setLoading] = useState(true); + const [success, setSuccess] = useState(true); + const [newOrdersData, setNewOrdersData] = useState([]); + console.log(newOrdersData); + + const [currentPage, setCurrentPage] = useState(1); + const [itemPerPage, setItemPerPage] = useState(10); + const [showData, setShowData] = useState(newOrdersData); + + const handleShowEntries = (e) => { + setCurrentPage(1); + setItemPerPage(e.target.value); + }; + + useEffect(() => { + function getNewOrder() { + axios + .get(`/api/order/getAll/new`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + const filteredOrders = res.data.order.filter( + (order) => order.orderType === "PointOfSale" && order.paymentMode === "online" + ); + + // Set the filtered orders data + setNewOrdersData(filteredOrders); + setLoading(false); + }) + .catch((err) => { + console.log(err); + setLoading(false); + }); + } + getNewOrder(); + }, [success]); + + + useEffect(() => { + const loadData = () => { + const indexOfLastPost = currentPage * itemPerPage; + const indexOfFirstPost = indexOfLastPost - itemPerPage; + setShowData(newOrdersData.slice(indexOfFirstPost, indexOfLastPost)); + }; + loadData(); + }, [currentPage, itemPerPage, newOrdersData]); + + const handleDelete = (id) => { + console.log(id); + swal({ + title: "Are you sure?", + icon: "error", + buttons: { + Yes: { text: "Yes", value: true }, + Cancel: { text: "Cancel", value: "cancel" }, + }, + }).then((value) => { + if (value === true) { + axios + .delete(`/api/order/delete/${id}`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + setSuccess((prev) => !prev); + }) + .catch((err) => { + swal({ + title: "Warning", + text: err.response.data.message + ? err.response.data.message + : "Something went wrong!", + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + } + }); + }; + + return ( +
+
+
+
+
+
+
+ New Orders +
+ + {/*
+ + + +
*/} +
+
+
+
+
+
+
+
+
+
+ +
+
+
+ +
+ + + + + + + + + + + + + {!loading && showData.length === 0 && ( + + + + )} + {loading ? ( + + + + ) : ( + showData.map((order, i) => { + return ( + + + + + + + + + ); + }) + )} + +
Order IDCustomerOrder valueOrder AtStatusActions
+
No Data Available
+
+ Loading... +
{order?.orderID} + {order?.user?.name} + + ₹{order?.total_amount} + + {new Date(order?.createdAt).toLocaleString( + "en-IN", + { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + } + )} + + + {order?.orderStatus} + + + {/* */} + + + + {/* + + */} + + {/* */} +
+
+ +
+
+
+ Showing {currentPage * itemPerPage - itemPerPage + 1} to{" "} + {Math.min( + currentPage * itemPerPage, + newOrdersData.length + )}{" "} + of {newOrdersData.length} entries +
+
+ +
+
+
    +
  • + setCurrentPage((prev) => prev - 1)} + > + Previous + +
  • + + {!(currentPage - 1 < 1) && ( +
  • + + setCurrentPage((prev) => prev - 1) + } + > + {currentPage - 1} + +
  • + )} + +
  • + + {currentPage} + +
  • + + {!( + (currentPage + 1) * itemPerPage - itemPerPage > + newOrdersData.length - 1 + ) && ( +
  • + { + setCurrentPage((prev) => prev + 1); + }} + > + {currentPage + 1} + +
  • + )} + +
  • + newOrdersData.length - 1 + ) + ? "paginate_button page-item next" + : "paginate_button page-item next disabled" + } + > + setCurrentPage((prev) => prev + 1)} + > + Next + +
  • +
+
+
+
+
+
+
+
+
+
+
+ ); +} + +export default InStoreQRCodeOrders; diff --git a/src/views/orders/NewOrders.js b/src/views/orders/NewOrders.js index 43c2621..f6acb81 100644 --- a/src/views/orders/NewOrders.js +++ b/src/views/orders/NewOrders.js @@ -31,7 +31,11 @@ function NewOrders() { }, }) .then((res) => { - setNewOrdersData(res.data.order); + const filteredOrders = res.data.order.filter( + (order) => order.orderType === "WebSite" + ); + + setNewOrdersData(filteredOrders); setLoading(false); }) .catch((err) => { @@ -41,6 +45,7 @@ function NewOrders() { } getNewOrder(); }, [success]); + useEffect(() => { const loadData = () => { diff --git a/src/views/orders/POSViewOrders.js b/src/views/orders/POSViewOrders.js new file mode 100644 index 0000000..7af4c55 --- /dev/null +++ b/src/views/orders/POSViewOrders.js @@ -0,0 +1,946 @@ +import React, { useState, useEffect, useRef } from "react"; +import axios from "axios"; +import { Link, useNavigate, useParams } from "react-router-dom"; +import QRCode from "react-qr-code"; +import { isAutheticated } from "src/auth"; +import { useDispatch, useSelector } from "react-redux"; +import { addItemsToCart } from "src/redux/Actions/cartAction"; +import toast from "react-hot-toast"; +import { cibBlackberry } from "@coreui/icons"; +import Button from "@material-ui/core/Button"; + +function POSViewOrders() { + const { status, id } = useParams(); + const [success, setSuccess] = useState(true); + + const { cartItems, subTotal, shippingCharge, tax, shipingInfo, total } = + useSelector((state) => state.cart); + + const AllStates = useSelector((state) => state); + const getValue = useRef(); + const getFranchiseeID = useRef(); + const dispatch = useDispatch(); + const navigate = useNavigate(); + const printOrderRef = useRef(); + const token = isAutheticated(); + const [productData, setProductData] = useState([]); + const [allFranchisee, setAllFranchisee] = useState([]); + const [allTax, setAllTax] = useState([]); + const [orderDetails, setOrderDetails] = useState(); + + const [productDetails, setProductDetails] = useState(); + const [loading, setLoading] = useState(true); + const [orderId, setOrderId] = useState(null); + const [orderStatus, setOrderStatus] = useState(""); + // const [data, setData] = useState({ + // product_Name: '', + // address: '', + // quantity: '', + // contact_Number: '', + // total_Price: '', + // }) + useEffect(() => { + const getSingleOrder = async () => { + setLoading(true); + const res = await axios.get(`/api/order/getOne/${id}`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }); + if (res.data) { + setLoading(false); + setOrderId(res.data?.order?.order_id); + setOrderDetails(res.data?.order); + console.log(res.data); + // let options = { + // Franchisee: res.data?.order?.shippingInfo?.Franchisee?._id, + // name: res.data?.order?.shippingInfo?.name, + + // contact_Number: res.data?.order?.shippingInfo?.contact_Number, + // contact_Person_Name: res.data?.order?.shippingInfo?.contact_Person_Name, + // address: res.data?.order?.shippingInfo?.address, + // city: res.data?.order?.shippingInfo?.city, + // price_Lable: res.data?.order?.shippingInfo?.Franchisee?.price_Lable, + // state: res.data?.order?.shippingInfo?.state, + // banner: res.data?.order?.shippingInfo?.Franchisee?.banner?.url, + // // Franchisee_Url: res?.data?.data?.url + // } + // dispatch({ type: "addShippingInfo", payload: options }); + // if (res.data?.order?.orderItems) { + // res.data?.order?.orderItems.map((i, ind) => { + // dispatch({ type: "addToCart", payload: i }); + // dispatch({ type: "calculatePrice" }); + + // }) + // } + } + }; + getSingleOrder(); + }, [token]); + + const handleChange = (e) => { + if (e.target.type === "text") { + setData((prev) => ({ ...prev, [e.target.id]: e.target.value })); + } else { + if (e.target.value === "") toast.error("please select status"); + setOrderStatus(e.target.value); + } + }; + const handleQuantityChange = (e) => { + setData((prev) => ({ + ...prev, + quantity: e.target.value, + total_Price: productDetails?.base_Price * e.target.value, + })); + }; + // ------------------------------------------------------ + + const handlechangestatus = () => { + if (orderStatus === "dispatched") { + swal({ + title: `Are you sure for ${orderStatus}?`, + icon: "warning", + content: { + element: "div", + attributes: { + innerHTML: + '' + + '', + }, + }, + buttons: { + Yes: { text: "Submit", value: true }, + + Cancel: { text: "Cancel", value: "cancel" }, + }, + }).then((result) => { + if (result === true) { + // You have the input values, you can use them in your API call + const courierName = document.getElementById("input1").value.trim(); + const TrackingID = document.getElementById("input2").value.trim(); + + // Check if values are entered + if (courierName === "" || TrackingID === "") { + swal({ + title: "Warning", + text: "Please enter values Courier Name And Tracking ID", + icon: "warning", + button: "Ok", + dangerMode: true, + }); + } else { + axios + .patch( + `/api/order/change/status/${id}`, + { + status: orderStatus, + courierName, + TrackingID, + sendemail: orderDetails?.user?.email, + customerName: orderDetails?.user?.name, + }, + { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + } + ) + .then((res) => { + console.log("status"); + toast.success( + `Order status change ${status} to ${orderStatus}` + ); + // setSuccess((prev) => !prev); + }) + .catch((err) => { + swal({ + title: "Warning", + text: err.response.data.message + ? err.response.data.message + : "Something went wrong!", + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + } + } + // else { + // swal.close(); // Close the popup if canceled + // } + }); + } else if (orderStatus === "cancelled") { + swal({ + title: `Are you sure for ${orderStatus}?`, + icon: "warning", + content: { + element: "div", + attributes: { + innerHTML: + '

Reson for cancellation.?

', + }, + }, + buttons: { + Yes: { text: "Submit", value: true }, + + Cancel: { text: "Cancel", value: "cancel" }, + }, + }).then((result) => { + if (result === true) { + // You have the input values, you can use them in your API call + const ReasonforCancellation = document + .getElementById("input1") + .value.trim(); + + // Check if values are entered + if (ReasonforCancellation === "") { + swal({ + title: "Warning", + text: "Please enter Reason for Cancellation", + icon: "warning", + button: "Ok", + dangerMode: true, + }); + } else { + axios + .patch( + `/api/order/change/status/${id}`, + { + status: orderStatus, + ReasonforCancellation, + }, + { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + } + ) + .then((res) => { + console.log("status"); + toast.success( + `Order status change ${status} to ${orderStatus}` + ); + // setSuccess((prev) => !prev); + }) + .catch((err) => { + swal({ + title: "Warning", + text: err.response.data.message + ? err.response.data.message + : "Something went wrong!", + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + } + } + // else { + // swal.close(); // Close the popup if canceled + // } + }); + } else if (orderStatus === "delivered") { + swal({ + title: `Are you sure for ${orderStatus}?`, + icon: "warning", + content: { + element: "div", + attributes: { + innerHTML: + '', + // '', + }, + }, + buttons: { + Yes: { text: "Submit", value: true }, + + Cancel: { text: "Cancel", value: "cancel" }, + }, + }).then((result) => { + if (result === true) { + // You have the input values, you can use them in your API call + const DDate = document.getElementById("input1").value.trim(); + + // Check if values are entered + if (DDate === "") { + swal({ + title: "Warning", + text: "Please enter Delivered Date", + icon: "warning", + button: "Ok", + dangerMode: true, + }); + } else { + axios + .patch( + `/api/order/change/status/${id}`, + { + status: orderStatus, + DDate, + }, + { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + } + ) + .then((res) => { + console.log("status"); + toast.success( + `Order status change ${status} to ${orderStatus}` + ); + // setSuccess((prev) => !prev); + }) + .catch((err) => { + swal({ + title: "Warning", + text: err.response.data.message + ? err.response.data.message + : "Something went wrong!", + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + } + } + // else { + // swal.close(); // Close the popup if canceled + // } + }); + } else { + swal({ + title: `Are you sure for ${orderStatus}?`, + icon: "warning", + + buttons: { + Yes: { text: "Yes", value: true }, + Cancel: { text: "Cancel", value: "cancel" }, + }, + }).then((value) => { + if (value === true) { + axios + .patch( + `/api/order/change/status/${id}`, + { status: orderStatus }, + { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + } + ) + .then((res) => { + console.log("status"); + toast.success(`order status change ${status} to ${orderStatus}`); + // setSuccess((prev) => !prev); + }) + .catch((err) => { + swal({ + title: "Warning", + text: err.response.data.message + ? err.response.data.message + : "Something went wrong!", + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + } + }); + } + }; + + function getBack() { + navigate(`/orders/${status}`, { replace: true }); + } + + return ( + <> + {" "} +
+
+
+
+
+
+
+

View Order

+
+
+ {orderDetails?.orderID && ( + +
Order ID : {orderDetails?.orderID}
{" "} +
+ )} +
+ {orderDetails?.courier_name && ( +
+ +
+ Courier Name: {orderDetails?.courier_name} +
{" "} +
+ Tracking ID : {orderDetails?.courier_tracking_id} +
+
+
+ )} + {orderDetails?.isDelivered && ( +
+ +
Delivered: Yes
{" "} +
+ Delivered Date: {orderDetails?.DeliveredDate} +
+
+
+ )} +
+ {/* */} + + + + +
+
+
+
+ {loading ? ( +
+
+ Loading... +
+
+ ) : ( +
+
+ {orderDetails?.shipingInfo !== null && ( +
+
+ {/*
+ +
+ + + +
+ +
*/} + +
+
+ Products : {orderDetails?.orderItems?.length} +
+
+ + {orderDetails?.orderItems && + orderDetails?.orderItems.map( + (productDetails, i) => ( +
+
+
+ {productDetails?.name} +
+
+
+ {productDetails?.name} +
+
+
+
+ + {" "} + Quantity:{" "} + {productDetails?.quantity} + +
+ +

+ Subtotal: ₹ + {productDetails?.quantity * + productDetails?.price} +

+

+ Variant:{" "} + {productDetails?.variant_Name} +

+
+
+

+ Price: ₹ + {productDetails?.price} +

+

+ GST: ₹ + {productDetails?.gst_amount} +

+
+
+
+
+
+
+ ) + )} +
+ Shipping Charge: ₹ + {orderDetails?.shipping_charge} +
+ Total Order Value: ₹ + {orderDetails?.total_amount} +
+
+
+
+ )} + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + {orderDetails?.status_timeline?.cancelled && ( + + + + + + )} + {/* + + + + */} + +
Order Placed On : + {orderDetails?.createdAt + ? new Date( + orderDetails?.createdAt + ).toLocaleString("en-IN", { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + }) + : new Date( + productData?.placed_on + ).toLocaleString("en-IN", { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + })} +
+ Processing Started + : + {orderDetails?.status_timeline?.processing + ? new Date( + orderDetails?.status_timeline?.processing + ).toLocaleString("en-IN", { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + }) + : "-"} +
+ Dispatched On + : + {orderDetails?.status_timeline?.dispatched + ? new Date( + orderDetails?.status_timeline?.dispatched + ).toLocaleString("en-IN", { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + }) + : "-"} +
+ Delivered On + : + {orderDetails?.status_timeline?.delivered + ? new Date( + orderDetails?.status_timeline?.delivered + ).toLocaleString("en-IN", { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + }) + : "-"} +
+ Cancelled On + : + {orderDetails?.status_timeline?.cancelled + ? new Date( + orderDetails?.status_timeline?.cancelled + ).toLocaleString("en-IN", { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + }) + : "-"} +
Returned On : + {orderDetails?.status_timeline?.returned + ? new Date( + orderDetails?.status_timeline?.returned + ).toLocaleString("en-IN", { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + }) + : "-"} +
+
+
+
+
+
+
+
+ {orderDetails?.orderStatus !== "cancelled" ? ( +
+ Order Status: {orderDetails?.orderStatus} +
+ ) : ( + <> +
+ Order Status: {orderDetails?.orderStatus} +
+

+ {" "} + Order Cancelled Reason:{" "} + {orderDetails?.order_Cancelled_Reason} +

+ + )} + {/* order status change */}{" "} +
+ {" "} + {status !== "cancelled" && + status !== "returned" && + status !== "delivered" && ( +
+ +
+
+ +
+ {orderStatus && ( +
+ +
+ )} +
+
+ )} +
+ {/* */} + + {/*
+ + +
*/} +
+ {orderDetails?.shipingInfo !== null && ( +
+
+ {/*
+ {orderDetails?.shippingInfo?.name} +
*/} +
+
+ Name: {orderDetails?.shippingInfo?.first_Name}{" "} + {orderDetails?.shippingInfo?.last_Name} +
+ +

+ Contact No. :{" "} + {orderDetails?.shippingInfo?.phone_Number} +

+ + street. : {orderDetails?.shippingInfo?.street} + + +

+ City : {orderDetails?.shippingInfo?.city} +

+

+ State : {orderDetails?.shippingInfo?.state} +

+

+ country : {orderDetails?.shippingInfo?.country} +

+

+ Postal Code. :{" "} + {orderDetails?.shippingInfo?.postalCode} +

+
+
+
+
+ )} +
+ +
+
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ )} +
+
+
+
+ {/* */} +
+ + ); +} + +export default POSViewOrders; From 37fd89be1f27129d78a45057dbfb460cbae9a746 Mon Sep 17 00:00:00 2001 From: roshangarg Date: Mon, 29 Apr 2024 17:22:48 +0530 Subject: [PATCH 4/6] edit ui for employee is done --- src/routes.js | 6 ++ src/views/EmployeeAccess/Employee.js | 3 + src/views/EmployeeAccess/editEmployee.js | 123 +++++++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 src/views/EmployeeAccess/editEmployee.js diff --git a/src/routes.js b/src/routes.js index 11c89e1..4f3aeb7 100644 --- a/src/routes.js +++ b/src/routes.js @@ -141,6 +141,7 @@ import EmailCms from "./views/CustomerSupport/EmailCMS/EmailCms"; import RegistrationEmail from "./views/CustomerSupport/EmailCMS/RegistrationEmail"; import Employee from "./views/EmployeeAccess/Employee"; import AddEmployee from "./views/EmployeeAccess/addEmployee"; +import EditEmployee from "./views/EmployeeAccess/editEmployee"; const routes = [ { path: "/", exact: true, name: "Home" }, { @@ -588,6 +589,11 @@ const routes = [ name: "Employee", element: AddEmployee, }, + { + path: "edit-employee/:id", + name: "Employee", + element: EditEmployee, + }, //Charts { path: "/new-user-day-wise", diff --git a/src/views/EmployeeAccess/Employee.js b/src/views/EmployeeAccess/Employee.js index c1b20b4..9b7a18d 100644 --- a/src/views/EmployeeAccess/Employee.js +++ b/src/views/EmployeeAccess/Employee.js @@ -333,6 +333,9 @@ const Employee = () => { Orders */} + + + + + ); +}; + +export default EditEmployee; From 2f739629d7c785aae24de4132a706333780e0678 Mon Sep 17 00:00:00 2001 From: Sibunnayak Date: Tue, 30 Apr 2024 17:15:51 +0530 Subject: [PATCH 5/6] point of sale variant wise select product and gst calculation fix and new order searching by name,orderid,date,city,mobileno etc implemented --- package.json | 2 +- src/views/PointOfSale/Pos.js | 314 +++++++++++------------------- src/views/dashboard/Dashboard.js | 2 +- src/views/orders/NewOrders.js | 291 ++++++++++++++++++++++----- src/views/orders/POSViewOrders.js | 3 +- 5 files changed, 362 insertions(+), 250 deletions(-) diff --git a/package.json b/package.json index 18a472f..2333507 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "react": "18.0.0", "react-bootstrap": "^2.7.0", "react-chartjs-2": "^5.2.0", - "react-datepicker": "^4.8.0", + "react-datepicker": "^4.25.0", "react-dom": "^18.0.0", "react-draft-wysiwyg": "^1.15.0", "react-hot-toast": "^2.4.0", diff --git a/src/views/PointOfSale/Pos.js b/src/views/PointOfSale/Pos.js index 3ed84b2..630b030 100644 --- a/src/views/PointOfSale/Pos.js +++ b/src/views/PointOfSale/Pos.js @@ -125,6 +125,8 @@ const Pos = () => { const [cartItem, setCartItem] = useState([]); const [individualSubtotals, setIndividualSubtotals] = useState([]); const [total, setTotal] = useState(0); + // varient + const [selectedVariants, setSelectedVariants] = useState({}); const getAllProducts = async () => { try { @@ -216,95 +218,91 @@ const Pos = () => { }, }; - const addToCart = (item) => { - // Check if the item is already in the cart with the same product ID and variant - const existingCartItemIndex = cartItem.findIndex( - (cartItem) => - cartItem.product._id === item._id && - cartItem.variant._id === selectedVariants[item._id]?._id - ); - - if (existingCartItemIndex !== -1) { - // Item with the same product ID and variant already exists in the cart, update its quantity - const newCart = [...cartItem]; - const existingCartItem = newCart[existingCartItemIndex]; + const addToCart = async (item) => { + try { const selectedVariant = selectedVariants[item._id]; - const price = selectedVariant ? selectedVariant.price : item.price; + if (selectedVariant) { + // Fetch tax details using the gstdetails function + const taxRate = selectedVariant?.gst_Id?.tax / 100; + const taxAmount = selectedVariant.price * taxRate; + const subtotal = + parseFloat(selectedVariant.price) + parseFloat(taxAmount); - existingCartItem.quantity += 1; - existingCartItem.subtotal += - parseFloat(price) + parseFloat(item.gst_amount); + const existingCartItemIndex = cartItem.findIndex( + (cartItem) => + cartItem.product._id === item._id && + cartItem.variant._id === selectedVariant._id + ); - setCartItem(newCart); - // Show a success message - swal("Item quantity updated in cart", "", "success"); - } else { - // Item is not in the cart, add it - const selectedVariant = selectedVariants[item._id]; - const price = selectedVariant ? selectedVariant.price : item.price; - const totalAmount = parseFloat(price) + parseFloat(item.gst_amount); + if (existingCartItemIndex !== -1) { + const newCart = [...cartItem]; + const existingCartItem = newCart[existingCartItemIndex]; - setCartItem([ - ...cartItem, - { - product: item, - quantity: 1, - variant: { - _id: selectedVariant?._id, - gst_Id: selectedVariant?.gst_Id, - price: selectedVariant?.price, - volume: selectedVariant?.volume, - weight: selectedVariant?.weight, - variant_Name: selectedVariant?.variant_Name, - }, - subtotal: totalAmount, - }, - ]); - // Show a success message - swal("Item added to cart", "", "success"); + existingCartItem.quantity += 1; + existingCartItem.subtotal = + parseFloat(existingCartItem.quantity) * + parseFloat(existingCartItem.subtotal); + + setCartItem(newCart); + swal("Item quantity updated in cart", "", "success"); + } else { + setCartItem([ + ...cartItem, + { + product: item, + quantity: 1, + variant: { + _id: selectedVariant._id, + gst_Id: selectedVariant.gst_Id, + price: selectedVariant.price, + volume: selectedVariant.volume, + weight: selectedVariant.weight, + variant_Name: selectedVariant.variant_Name, + }, + subtotal: subtotal.toFixed(2), // Format the subtotal to two decimal places + }, + ]); + swal("Item added to cart", "", "success"); + } + } + } catch (error) { + console.error("Error adding item to cart:", error); + swal("Error", "Failed to add item to cart", "error"); } }; const handleIncrease = (index) => { const newCart = [...cartItem]; const item = newCart[index]; - - const selectedVariant = selectedVariants[item.product._id]; - const price = selectedVariant ? selectedVariant.price : item.product.price; + const taxRate = item.variant?.gst_Id?.tax / 100; + const taxAmount = item.variant?.price * taxRate; + const price = item.variant ? item.variant?.price : item.product.price; const totalAmount = - (item.quantity + 1) * parseFloat(price) + - parseFloat(item.product.gst_amount); + (item.quantity + 1) * (parseFloat(price) + parseFloat(taxAmount)); newCart[index].quantity += 1; newCart[index].subtotal = totalAmount; setCartItem(newCart); }; - const handleDecrease = (index) => { const newCart = [...cartItem]; const item = newCart[index]; + const taxRate = item.variant?.gst_Id?.tax / 100; + const taxAmount = item.variant?.price * taxRate; + const price = item.variant ? item.variant?.price : item.product.price; + const totalAmount = + (item.quantity - 1) * (parseFloat(price) + parseFloat(taxAmount)); - if (item.quantity > 1) { - const selectedVariant = selectedVariants[item.product._id]; - const price = selectedVariant - ? selectedVariant.price - : item.product.price; - const totalAmount = - (item.quantity - 1) * parseFloat(price) + - parseFloat(item.product.gst_amount); + newCart[index].quantity -= 1; + newCart[index].subtotal = totalAmount; - newCart[index].quantity -= 1; - newCart[index].subtotal = totalAmount; - - setCartItem(newCart); - } + setCartItem(newCart); }; - // console.log(cartItem) const removeCartItemHandler = (id, variant) => { const newCart = cartItem.filter( - (item) => item?.product._id !== id || item.variant._id !== variant + (item) => item.product._id !== id || item.variant._id !== variant ); setCartItem(newCart); }; @@ -313,14 +311,17 @@ const Pos = () => { const calculateTotal = () => { let subtotal = 0; cartItem.forEach((item) => { - subtotal += item.subtotal; + subtotal += parseFloat(item.subtotal); }); - setTotal(subtotal); + // Round the subtotal to two decimal places + const roundedSubtotal = parseFloat(subtotal.toFixed(2)); + setTotal(roundedSubtotal); }; useEffect(() => { calculateTotal(); }, [cartItem]); + // console.log(usersWithAddresses); const [showChangeAddress, setShowChangeAddress] = useState(false); const [selectedAddress, setSelectedAddress] = useState( @@ -338,71 +339,6 @@ const Pos = () => { setShowChangeAddress(false); }; - // const checkoutCash = async () => { - // // console.log("Checkout button clicked"); - // try { - // const config = { - // headers: { - // Authorization: `Bearer ${token}`, - // }, - // }; - // const cartData = cartItem.map((item) => ({ - // product: item.product, // Entire product object - // quantity: item.quantity, - // variant: item.variant, // Entire variant object - // subtotal: item.subtotal, - // })); - // const order = { - // userr: currentUser._id, - // address: selectedAddress._id, - // cart: cartData, - // subtotal: total, - // orderType: "PointOfSale", - // }; - - // // Send POST request to backend API endpoint - // const response = await axios.post( - // "/api/order/pos-checkout/", - // order, - // config - // ); - - // toast.success("Order Placed! Your order has been successfully placed."); - // swal({ - // title: "Order Placed!", - // text: `Order ID: ${ - // response.data.order.orderID - // }\nDate and Time: ${new Date( - // response.data.order.createdAt - // ).toLocaleString("en-IN", { - // month: "short", - // day: "numeric", - // year: "numeric", - // hour: "2-digit", - // minute: "numeric", - // hour12: true, - // })}`, - // icon: "success", - // button: "OK", - // }); - - // // Clear cart items, reset current user and address, and reset radio button states - // setCartItem([]); - // setCurrentUser(null); - // setSelectedAddress(null); - // setSalesType(""); - // setStoreDelivery(""); - // setTotal(0); - // setCategoryValue("All"); - // } catch (error) { - // // Handle errors - // console.error("Error placing order:", error); - - // toast.error( - // "Error! There was an error placing your order. Please try again later." - // ); - // } - // }; const checkoutCash = async () => { const config = { headers: { @@ -518,8 +454,8 @@ const Pos = () => { order_id: order.id, // callback_url: // "http://localhost:5000/api/order/pos-paymentverification/", - callback_url: - "https://api.smellika.com/api/order/pos-paymentverification/", + callback_url: + "https://api.smellika.com/api/order/pos-paymentverification/", prefill: { name: currentUser.name, @@ -555,8 +491,6 @@ const Pos = () => { } } }; - // varient - const [selectedVariants, setSelectedVariants] = useState({}); // Function to set default variant for each product const setDefaultVariants = () => { @@ -1162,7 +1096,12 @@ const Pos = () => { color: "#121212", }} > - ₹{row?.product.gst_amount} + ₹ + {Number( + (row.variant?.price * + row.variant?.gst_Id?.tax) / + 100 + )?.toFixed(2)} { color: "#121212", }} > - ₹{row.subtotal} + ₹{Number(row?.subtotal)?.toFixed(2)} )) @@ -1200,82 +1139,65 @@ const Pos = () => { style={{ display: "flex", justifyContent: "space-between" }} >
- {/* {salesType === "" ? null : salesType === - "inStoreDelivery" ? ( */} -
- - In-Store delivery: - -
- - -
-
- - -
- {storedelivery && ( - - )} -
- {/* ) : ( -
- {salesType === "shipToCustomer" && ( - - )} - {salesType !== "shipToCustomer" && ( + In-Store delivery: + +
+ + +
+
+ + +
+ {storedelivery && ( )}
- )} */} + ) : ( +
+

+ Please Add user and their address to place the order +

+
+ )}
{/* Total Section */} diff --git a/src/views/dashboard/Dashboard.js b/src/views/dashboard/Dashboard.js index 805fa64..930b58a 100644 --- a/src/views/dashboard/Dashboard.js +++ b/src/views/dashboard/Dashboard.js @@ -33,7 +33,7 @@ const Dashboard = () => { //3rd const [product, setProduct] = useState([]); const getAllProduct = async () => { - let res = await axios.get(`/api/product/getAll/`, { + let res = await axios.get(`/api/product/getAll/user/`, { headers: { Authorization: `Bearer ${token}`, }, diff --git a/src/views/orders/NewOrders.js b/src/views/orders/NewOrders.js index f6acb81..5b3aec5 100644 --- a/src/views/orders/NewOrders.js +++ b/src/views/orders/NewOrders.js @@ -4,13 +4,19 @@ import axios from "axios"; import { isAutheticated } from "src/auth"; import Button from "@material-ui/core/Button"; +import { cilSearch } from "@coreui/icons"; +import CIcon from "@coreui/icons-react"; +import { TextField, FormControl, Select, MenuItem } from "@material-ui/core"; +import { Typography } from "@material-ui/core"; +import DatePicker from "react-datepicker"; +import "react-datepicker/dist/react-datepicker.css"; function NewOrders() { const token = isAutheticated(); const [loading, setLoading] = useState(true); const [success, setSuccess] = useState(true); const [newOrdersData, setNewOrdersData] = useState([]); - console.log(newOrdersData); + // console.log(newOrdersData); const [currentPage, setCurrentPage] = useState(1); const [itemPerPage, setItemPerPage] = useState(10); @@ -21,40 +27,31 @@ function NewOrders() { setItemPerPage(e.target.value); }; - useEffect(() => { - function getNewOrder() { - axios - .get(`/api/order/getAll/new`, { - headers: { - "Access-Control-Allow-Origin": "*", - Authorization: `Bearer ${token}`, - }, - }) - .then((res) => { - const filteredOrders = res.data.order.filter( - (order) => order.orderType === "WebSite" - ); - - setNewOrdersData(filteredOrders); - setLoading(false); - }) - .catch((err) => { - console.log(err); - setLoading(false); - }); - } - getNewOrder(); - }, [success]); - + function getNewOrder() { + axios + .get(`/api/order/getAll/new`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + const filteredOrders = res.data.order.filter( + (order) => order.orderType === "WebSite" + ); + setNewOrdersData(filteredOrders); + setLoading(false); + }) + .catch((err) => { + console.log(err); + setLoading(false); + }); + } useEffect(() => { - const loadData = () => { - const indexOfLastPost = currentPage * itemPerPage; - const indexOfFirstPost = indexOfLastPost - itemPerPage; - setShowData(newOrdersData.slice(indexOfFirstPost, indexOfLastPost)); - }; - loadData(); - }, [currentPage, itemPerPage, newOrdersData]); + setLoading(true); + getNewOrder(); + }, [token]); const handleDelete = (id) => { console.log(id); @@ -91,7 +88,94 @@ function NewOrders() { } }); }; + const [searchTerm, setSearchTerm] = useState(""); + const [searchValue, setsearchValue] = useState("orderId"); + const handleChange = (event) => { + const { name, value } = event.target; + if (name === "Search") { + setsearchValue(value); + } + }; + const formatDate = (dateString) => { + const dateArray = dateString.split(" "); + const day = dateArray[0]; + const month = dateArray[1]; + const year = dateArray[2]; + const monthNumber = new Date(Date.parse(`${month} 1, 2022`)).getMonth() + 1; + return `${year}-${ + monthNumber < 10 ? "0" + monthNumber : monthNumber + }-${day}`; + }; + // const formatDate = (date) => { + // const day = ("0" + date.getDate()).slice(-2); + // const month = ("0" + (date.getMonth() + 1)).slice(-2); + // const year = date.getFullYear(); + // return `${year}-${month}-${day}`; + // }; + console.log(searchTerm); + useEffect(() => { + setTimeout(() => { + if (searchTerm !== "") { + let searchedResult = []; + if (searchValue === "orderId") { + searchedResult = newOrdersData.filter((item) => + item.orderID.toString().includes(searchTerm) + ); + } else if (searchValue === "Name") { + searchedResult = newOrdersData.filter((item) => + item.user?.name + .toString() + .toLowerCase() + .includes(searchTerm.toLowerCase()) + ); + } else if (searchValue === "City") { + searchedResult = newOrdersData.filter((item) => + item.shippingInfo.city + .toString() + .toLowerCase() + .includes(searchTerm.toLowerCase()) + ); + } else if (searchValue === "Amount") { + searchedResult = newOrdersData.filter((item) => + item.total_amount.toString().includes(searchTerm) + ); + } else if (searchValue === "OrderDate") { + // Format input date + const formattedDate = formatDate(searchTerm); + searchedResult = newOrdersData.filter((item) => + item.createdAt.includes(formattedDate) + ); + } else if (searchValue === "ProductName") { + searchedResult = newOrdersData.filter((order) => + order.orderItems.some((item) => + item.name + .toString() + .toLowerCase() + .includes(searchTerm.toLowerCase()) + ) + ); + } else if (searchValue === "MobileNumber") { + searchedResult = newOrdersData.filter((item) => + item.shippingInfo.phone_Number.toString().includes(searchTerm) + ); + } + + setShowData(searchedResult); + } else { + getNewOrder(); + } + }, 100); + }, [searchTerm, searchValue, newOrdersData]); + + useEffect(() => { + const loadData = () => { + const indexOfLastPost = currentPage * itemPerPage; + const indexOfFirstPost = indexOfLastPost - itemPerPage; + setShowData(newOrdersData.slice(indexOfFirstPost, indexOfLastPost)); + }; + loadData(); + }, [currentPage, itemPerPage, newOrdersData]); return (
@@ -132,28 +216,135 @@ function NewOrders() {
-
-
-
- +
+
+
+
+
+ + Search by : + + + - entries - + + orderId + + + Name + + + City + + + Amount + + + OrderDate + + + ProductName + + + MobileNumber + + + +
+ {/*
+ {searchValue === "OrderDate" && ( + setSearchTerm(date)} + dateFormat="dd/MM/yyyy" + placeholderText="Select a date" + /> + )} + {searchValue !== "OrderDate" && ( + setSearchTerm(e.target.value)} + /> + )} + +
*/} +
+ setSearchTerm(e.target.value)} + /> +
diff --git a/src/views/orders/POSViewOrders.js b/src/views/orders/POSViewOrders.js index 7af4c55..0c3c263 100644 --- a/src/views/orders/POSViewOrders.js +++ b/src/views/orders/POSViewOrders.js @@ -529,8 +529,7 @@ function POSViewOrders() {

Subtotal: ₹ - {productDetails?.quantity * - productDetails?.price} + {productDetails?.product_Subtotal}

Variant:{" "} From 0581cf77fed28a27d4ffe8a5e27c7175e24a5104 Mon Sep 17 00:00:00 2001 From: roshangarg Date: Fri, 3 May 2024 10:34:47 +0530 Subject: [PATCH 6/6] added employee section --- package.json | 4 +- src/_nav.js | 16 +- src/components/AppContent.js | 21 +- src/components/AppSidebar.js | 55 +- src/index.js | 4 +- src/routes.js | 58 +- src/views/EmployeeAccess/Employee.js | 284 ++--- src/views/EmployeeAccess/addEmployee.js | 115 +- src/views/EmployeeAccess/editEmployee.js | 99 +- src/views/dashboard/Dashboard.js | 2 +- src/views/exportExcel.js | 73 ++ src/views/orders/AddOrder.js | 1387 +++++++++++----------- src/views/orders/EditOrder.js | 2 +- src/views/pages/login/Login.js | 4 +- 14 files changed, 1170 insertions(+), 954 deletions(-) create mode 100644 src/views/exportExcel.js diff --git a/package.json b/package.json index 18a472f..42c60d4 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "draft-js": "^0.11.7", "draft-js-export-html": "^1.4.1", "draft-js-import-html": "^1.4.1", + "file-saver": "^2.0.5", "md5": "^2.3.0", "moment": "^2.30.1", "prop-types": "^15.7.2", @@ -76,7 +77,8 @@ "styled-components": "^6.0.8", "sweetalert": "^2.1.2", "sweetalert2": "^11.4.0", - "uuid": "^9.0.1" + "uuid": "^9.0.1", + "xlsx": "^0.18.5" }, "devDependencies": { "auto-changelog": "~2.3.0", diff --git a/src/_nav.js b/src/_nav.js index ca0faf1..13e578e 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -323,17 +323,17 @@ const _nav = [ // Employee { component: CNavItem, - name: "Employee", + name: " Employees & Access", icon: , to: "/employee", }, -//Point of Sale start -{ - component: CNavItem, - name: "Point of Sale", - icon: , - to: "/pos", -}, + //Point of Sale start + { + component: CNavItem, + name: "Point of Sale", + icon: , + to: "/pos", + }, // { // component: CNavGroup, // name: "Blog", diff --git a/src/components/AppContent.js b/src/components/AppContent.js index f3c74be..715dbd6 100644 --- a/src/components/AppContent.js +++ b/src/components/AppContent.js @@ -1,16 +1,17 @@ -import React, { Suspense } from 'react' -import { Navigate, Route, Routes } from 'react-router-dom' -import { CContainer, CSpinner } from '@coreui/react' +import React, { Suspense, useState } from "react"; +import { Navigate, Route, Routes } from "react-router-dom"; +import { CContainer, CSpinner } from "@coreui/react"; // routes config -import routes from '../routes' +import routes from "../routes"; const AppContent = () => { + const [appRoutes, setAppRoutes] = useState(routes); return ( }> - {routes.map((route, idx) => { + {appRoutes.map((route, idx) => { return ( route.element && ( { element={} /> ) - ) + ); })} } /> - ) -} + ); +}; - - -export default React.memo(AppContent) +export default React.memo(AppContent); diff --git a/src/components/AppSidebar.js b/src/components/AppSidebar.js index 79ec9c5..6f921d9 100644 --- a/src/components/AppSidebar.js +++ b/src/components/AppSidebar.js @@ -27,12 +27,61 @@ const AppSidebar = () => { const dispatch = useDispatch(); const unfoldable = useSelector((state) => state.sidebarUnfoldable); const sidebarShow = useSelector((state) => state.sidebarShow); + const [navigationItem, setNavigationItem] = useState(navigation); + + const [userdata, setUserData] = useState(null); + const token = isAutheticated(); + console.log("userDatt", userdata); + + useEffect(() => { + const getUser = async () => { + let existanceData = localStorage.getItem("authToken"); + if (!existanceData) { + // console.log(existanceData.userData) + setUserData(false); + } else { + try { + // console.log('requesting user data from server') + let response = await axios.get(`/api/v1/user/details`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + // console.log(response.data) + const data = response.data; + if ( + (data.success && data.user.role === "admin") || + data.user.role === "Employee" + ) { + setUserData(data.user); + } else { + setUserData(false); + } + } catch (err) { + setUserData(false); + console.log(err); + } + } + }; + getUser(); + }, []); + useEffect(() => { + if (userdata && userdata.accessTo) { + const filteredNavigation = navigation.filter((item) => { + if (userdata.accessTo[item.name]) { + return true; + } + return false; + }); + setNavigationItem(filteredNavigation); + } else { + setNavigationItem(navigation); + } + }, [userdata]); ///----------------------// const [loading, setLoading] = useState(false); - const token = isAutheticated(); - // urlcreated images const [AppName, setAppName] = useState(""); const [HeaderlogoUrl, setHeaderlogoUrl] = useState(""); @@ -87,7 +136,7 @@ const AppSidebar = () => { - + { - // axios.defaults.baseURL = "http://localhost:5000"; - axios.defaults.baseURL = "https://api.smellika.com"; + axios.defaults.baseURL = "http://localhost:5000"; + // axios.defaults.baseURL = "https://api.smellika.com"; axios.defaults.headers = { "Cache-Control": "no-cache,no-store", diff --git a/src/routes.js b/src/routes.js index 6c8307a..c9db5aa 100644 --- a/src/routes.js +++ b/src/routes.js @@ -146,6 +146,7 @@ import RegistrationEmail from "./views/CustomerSupport/EmailCMS/RegistrationEmai import Employee from "./views/EmployeeAccess/Employee"; import AddEmployee from "./views/EmployeeAccess/addEmployee"; import EditEmployee from "./views/EmployeeAccess/editEmployee"; +import ExportToExcel from "./views/exportExcel"; const routes = [ { path: "/", exact: true, name: "Home" }, { @@ -187,17 +188,17 @@ const routes = [ { path: "/customers-details", - name: "User Table", + name: "Customers", element: CustomerTable, }, { path: "/customers-details/:_id", - name: "User Table", + name: "Customers", element: SingleUserAllDetails, }, { path: "/add-customer", - name: "User Table", + name: "Customers", element: AddCustomer, }, // { @@ -212,7 +213,7 @@ const routes = [ // }, { path: "/users-address/view", - name: "view address", + name: "Customers", element: viewDetails, }, @@ -275,12 +276,12 @@ const routes = [ { path: "/contact/request", - name: "Contact Requests", + name: "Customer Service", element: ContactRequests, }, { path: "/contact/request/new", - name: "AddContact Request", + name: "Customer Service", element: AddContactRequest, }, //Support Requests @@ -297,54 +298,54 @@ const routes = [ { path: "/support/request", - name: "CustomerSupport Requests", + name: "Customer Service", element: SupportRequest, }, { path: "/support/request/closed", - name: "Closed CustomerSupport Requests", + name: "Customer Service", element: SupportRequestClosed, }, { path: "/support/request/closed/:ticketID", - name: "Closed CustomerSupport Request view", + name: "Customer Service", element: CloseRequestView, }, { path: "/support/request/reply/:ticketID", - name: "CustomerSupport Reply", + name: "Customer Service", element: SupportReply, }, // Content ---- > { path: "/content", - name: "Content", + name: "Website Relatedt", element: Content, }, { path: "/content/terms-and-conditions", - name: "Content", + name: "Website Related", element: EditTermsConditions, }, { path: "/content/privacy-policy", - name: "Content", + name: "Website Related", element: EditPrivacyPolicy, }, { path: "/content/shipping-policy", - name: "Content", + name: "Website Related", element: EditShippingPolicy, }, { path: "/content/refund-policy", - name: "Content", + name: "Website Related", element: EditRefundpolicy, }, { path: "/content/about-us", - name: "Content", + name: "Website Related", element: EditAboutUs, }, @@ -459,9 +460,21 @@ const routes = [ element: ReturnedOrders, }, //Point of sale orders - { path: "/inStoreCashOrders/new", name: "In Store Cash Orders", element:InStoreCashOrders }, - { path: "/InStoreQRCodeOrders/new", name: "In Store QR Code Orders", element:InStoreQRCodeOrders }, - { path: "/inStoreOrders/:status/:id", name: "View In Store Cash Orders", element: POSViewOrders }, + { + path: "/inStoreCashOrders/new", + name: "In Store Cash Orders", + element: InStoreCashOrders, + }, + { + path: "/InStoreQRCodeOrders/new", + name: "In Store QR Code Orders", + element: InStoreQRCodeOrders, + }, + { + path: "/inStoreOrders/:status/:id", + name: "View In Store Cash Orders", + element: POSViewOrders, + }, // { path: "/order/:status/:id", name: "View Order", element: ViewOdr }, //dashboard @@ -639,6 +652,13 @@ const routes = [ name: "Point of Sale", element: Pos, }, + + // Export to excel + { + path: "/exp", + name: "Point of Sale", + element: ExportToExcel, + }, ]; export default routes; diff --git a/src/views/EmployeeAccess/Employee.js b/src/views/EmployeeAccess/Employee.js index 9b7a18d..2650f39 100644 --- a/src/views/EmployeeAccess/Employee.js +++ b/src/views/EmployeeAccess/Employee.js @@ -25,26 +25,35 @@ const Employee = () => { const [loading, setLoading] = useState(true); const [loading1, setLoading1] = useState(true); const [success, setSuccess] = useState(true); - const [users, setUsers] = useState([]); + const [employee, setemployee] = useState([]); const [currentPage, setCurrentPage] = useState(1); const [itemPerPage, setItemPerPage] = useState(10); - const [showData, setShowData] = useState(users); + const [showData, setShowData] = useState(employee); const handleShowEntries = (e) => { setCurrentPage(1); setItemPerPage(e.target.value); }; + useEffect(() => { + const loadData = () => { + const indexOfLastPost = currentPage * itemPerPage; + const indexOfFirstPost = indexOfLastPost - itemPerPage; + setShowData(employee.slice(indexOfFirstPost, indexOfLastPost)); + }; + loadData(); + }, [currentPage, itemPerPage, employee]); + console.log(employee); - // const getUsers = async () => { + // const getemployee = async () => { // axios - // .get(`/api/v1/admin/users`, { + // .get(`/api/v1/admin/employee`, { // headers: { // Authorization: `Bearer ${token}`, // }, // }) // .then((res) => { - // setUsers(res.data.users); + // setemployee(res.data.employee); // setLoading(false); // }) // .catch((error) => { @@ -60,19 +69,19 @@ const Employee = () => { // }; // useEffect(() => { - // getUsers(); + // getemployee(); // }, [success]); - // console.log(users); + // console.log(employee); // useEffect(() => { // const loadData = () => { // const indexOfLastPost = currentPage * itemPerPage; // const indexOfFirstPost = indexOfLastPost - itemPerPage; - // setShowData(users.slice(indexOfFirstPost, indexOfLastPost)); + // setShowData(employee.slice(indexOfFirstPost, indexOfLastPost)); // }; // loadData(); - // }, [currentPage, itemPerPage, users]); - // console.log(users); + // }, [currentPage, itemPerPage, employee]); + // console.log(employee); // const handleDelete = (id) => { // swal({ @@ -113,6 +122,70 @@ const Employee = () => { // }); // }; + // get All employee + const getemployee = async () => { + axios + .get(`/api/v1/admin/employee`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + setemployee(res.data.employee); + 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); + }); + }; + useEffect(() => { + getemployee(); + }, [success]); + console.log(employee); + console.log("showdata", showData); + // const trueEntries = Object.entries(showData.).filter( + // ([key, value]) => value === true + // ); + const renderAccessTo = (accessTo) => { + return Object.entries(accessTo) + .filter(([key, value]) => value === true) + .map(([key, value]) => key) + .join(", "); + }; + const handleDelete = async (id) => { + try { + // Send a DELETE request to your API to delete the employee by ID + const res = await axios.delete(`/api/v1/admin/delete-employee/${id}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + // If deletion is successful, update the employee list + swal({ + title: "Congratulations!!", + text: res?.data?.message, + icon: "success", + buttons: "OK", + }); + setemployee(employee.filter((employee) => employee._id !== id)); + } catch (error) { + console.error("Error deleting employee:", error); + swal({ + title: "", + text: "Something went wrong!", + icon: "error", + button: "Retry", + dangerMode: true, + }); + } + }; return (

@@ -207,168 +280,67 @@ const Employee = () => { )} - {!loading ? ( + {loading ? ( Loading... ) : ( - // showData.map((user, i) => { - // return ( - // - // {user.name} - // {user._id} + showData.map((employee, i) => { + return ( + + {employee.name} + {employee.email} - // - // {new Date(user.createdAt).toLocaleString( - // "en-IN", - // { - // weekday: "short", - // month: "short", - // day: "numeric", - // year: "numeric", - // hour: "numeric", - // minute: "numeric", - // hour12: true, - // } - // )} - // - // {loading1 && ( - // <> - // loading... - // loading... - // - // )} + + {renderAccessTo(employee.accessTo)} + - // - - // - // {/* - // - // - // - // - // - // - // - // */} - // - // - // - // - // - // ); - // }) - - Roshan Garg - roshan@gmail.com - {/* Profile Image */} - dashboard - - {/* Last Purchase - Orders */} - - - - - + > + Delete + + + + ); + }) )} @@ -383,8 +355,8 @@ const Employee = () => { aria-live="polite" > Showing {currentPage * itemPerPage - itemPerPage + 1} to{" "} - {Math.min(currentPage * itemPerPage, users.length)} of{" "} - {users.length} entries + {Math.min(currentPage * itemPerPage, employee.length)}{" "} + of {employee.length} entries
@@ -432,7 +404,7 @@ const Employee = () => { {!( (currentPage + 1) * itemPerPage - itemPerPage > - users.length - 1 + employee.length - 1 ) && (
  • { className={ !( (currentPage + 1) * itemPerPage - itemPerPage > - users.length - 1 + employee.length - 1 ) ? "paginate_button page-item next" : "paginate_button page-item next disabled" diff --git a/src/views/EmployeeAccess/addEmployee.js b/src/views/EmployeeAccess/addEmployee.js index b0efd0d..4c9fb9e 100644 --- a/src/views/EmployeeAccess/addEmployee.js +++ b/src/views/EmployeeAccess/addEmployee.js @@ -5,32 +5,109 @@ import FormControlLabel from "@mui/material/FormControlLabel"; import Checkbox from "@mui/material/Checkbox"; import { useNavigate } from "react-router-dom"; import _nav from "src/_nav"; +import toast from "react-hot-toast"; +import axios from "axios"; const AddEmployee = () => { const [employeeName, setEmployeeName] = useState(""); + const [phone, setPhone] = useState(""); const [email, setEmail] = useState(""); const navigate = useNavigate(); - const [checkedItems, setCheckedItems] = useState({}); + const filteredNav = _nav.filter((item) => item.name !== "Employee"); + const [checkedItems, setCheckedItems] = useState( + filteredNav.reduce((acc, item) => { + acc[item.name] = false; + return acc; + }, {}) + ); + + // const filteredEntries = Object.fromEntries( + // Object.entries(checkedItems).filter(([key, value]) => value === true) + // ); + // console.log(filteredEntries); const handleCheckboxChange = (name) => (event) => { setCheckedItems({ ...checkedItems, [name]: event.target.checked, }); }; + console.log(checkedItems); + const generatePassword = (name, email) => { + const combinedStr = (name + email).toLowerCase(); // Convert to lowercase for consistency + const specialChars = "@#*!$%^&"; // Define the set of special characters + const alphaChars = combinedStr.match(/[a-zA-Z]/g); // Filter out alphabetic characters + const digitChars = combinedStr.match(/\d/g); // Filter out digits + const filteredChars = combinedStr.match(/[^\W_]/g); // Filter out non-alphanumeric characters + let passwordChars = alphaChars.concat(filteredChars); // Combine alphabetic and filtered characters + + // Ensure at least one uppercase letter + if (!passwordChars.some((char) => char === char.toUpperCase())) { + const uppercaseChar = String.fromCharCode( + 65 + Math.floor(Math.random() * 26) + ); + passwordChars.push(uppercaseChar); + } + + // Ensure at least one digit + if (!digitChars || digitChars.length === 0) { + const digitChar = Math.floor(Math.random() * 10).toString(); + passwordChars.push(digitChar); + } + + // Insert a random special character at a random position in the password characters array + const specialChar = specialChars.charAt( + Math.floor(Math.random() * specialChars.length) + ); + const randomIndex = Math.floor(Math.random() * (passwordChars.length + 1)); + passwordChars.splice(randomIndex, 0, specialChar); + + passwordChars = passwordChars.sort(() => Math.random() - 0.5); // Shuffle the characters + // passwordString.charAt(0).toUpperCase() + passwordString.slice(1) + "@"; + const normalpassword = passwordChars.join("").slice(0, 8); // Take the first 8 characters + const passwordWithspecialChar = + normalpassword.charAt(0).toUpperCase() + normalpassword.slice(1) + "1@2"; + return passwordWithspecialChar; + }; + + const handleFormSubmit = async (e) => { + e.preventDefault(); + console.log("request made"); + try { + if (!employeeName || !email || !phone) { + throw new Error("Fill all fields!"); + } + + // Generate password based on name and email + const generatedPassword = generatePassword(employeeName, email); + console.log(generatedPassword); // Use generatedPassword instead of generatePassword + // Set generated password to user state + + const response = await axios.post("/api/v1/user/register", { + // Send user details + name: employeeName, + email: email, + phone: phone, + role: "Employee", + accessTo: checkedItems, + password: generatedPassword, // Send generated password to the backend + }); + console.log(response); + if (response.status === 201) { + toast.success("Employee Added Successful"); + // setUserId(response.data.userId); + navigate("/employee"); + } + } catch (error) { + console.log(error?.response); + // toast.error(error?.response); + } + }; return (
    - {/* setTitle(e.target.value)} - variant="outlined" - size="small" - fullWidth - /> */} { onChange={(e) => setEmployeeName(e.target.value)} />
    +
    + + + setPhone(e.target.value)} + /> +
    + ); +} + +export default ExportToExcel; diff --git a/src/views/orders/AddOrder.js b/src/views/orders/AddOrder.js index f6b217d..c546963 100644 --- a/src/views/orders/AddOrder.js +++ b/src/views/orders/AddOrder.js @@ -1,738 +1,717 @@ - - - -import React, { useState, useEffect, useRef } from 'react' -import axios from 'axios' -import { Link, useNavigate, useParams } from 'react-router-dom' -import QRCode from 'react-qr-code' -import { isAutheticated } from 'src/auth' -import { useDispatch, useSelector } from 'react-redux' -import { addItemsToCart } from 'src/redux/Actions/cartAction' -import toast from 'react-hot-toast' -import { cibBlackberry } from '@coreui/icons' -import Button from '@material-ui/core/Button' +import React, { useState, useEffect, useRef } from "react"; +import axios from "axios"; +import { Link, useNavigate, useParams } from "react-router-dom"; +import QRCode from "react-qr-code"; +import { isAutheticated } from "src/auth"; +import { useDispatch, useSelector } from "react-redux"; +import { addItemsToCart } from "src/redux/Actions/cartAction"; +import toast from "react-hot-toast"; +import { cibBlackberry } from "@coreui/icons"; +import Button from "@material-ui/core/Button"; function AddOrder() { - const { status, id } = useParams() + const { status, id } = useParams(); - const { cartItems, subTotal, shippingCharge, tax, shipingInfo, total } = useSelector( - (state) => state.cart - ); + const { cartItems, subTotal, shippingCharge, tax, shipingInfo, total } = + useSelector((state) => state.cart); + const AllStates = useSelector((state) => state); + const getValue = useRef(); + const getFranchiseeID = useRef(); + const dispatch = useDispatch(); + const navigate = useNavigate(); + const printOrderRef = useRef(); + const token = isAutheticated(); + const [productData, setProductData] = useState([]); + const [allFranchisee, setAllFranchisee] = useState([]); + const [allTax, setAllTax] = useState([]); - const AllStates = useSelector( - (state) => state - ); - const getValue = useRef() - const getFranchiseeID = useRef() - const dispatch = useDispatch(); - const navigate = useNavigate() - const printOrderRef = useRef() - const token = isAutheticated() - const [productData, setProductData] = useState([]) - const [allFranchisee, setAllFranchisee] = useState([]) - const [allTax, setAllTax] = useState([]) - - - - const [productDetails, setProductDetails] = useState() - const [loading, setLoading] = useState(true) - const [orderStatus, setOrderStatus] = useState('') - const [data, setData] = useState({ - product_Name: '', - address: '', - quantity: '', - contact_Number: '', - total_Price: '', - }) - useEffect(() => { - const getAllTax = async () => { - const res = await axios.get(`/api/tax/view_tax`, { - headers: { 'Access-Control-Allow-Origin': '*', Authorization: `Bearer ${token}` }, - }) - if (res.data) { - // console.log(res.data) - setAllTax(res.data) - } - } - getAllTax() - - }, [token]) - - useEffect(() => { - function getProductDetails() { - setLoading(true) - axios - .get(`/api/product/getAll/`, { - headers: { 'Access-Control-Allow-Origin': '*', Authorization: `Bearer ${token}` }, - }) - .then((res) => { - setLoading(false) - // console.log(res.data.product) - setProductData(res.data.product) - }) - .catch((err) => { - setLoading(false) - // getBack() - }) - } - function getFranchiseeDetails() { - setLoading(true) - axios - .get(`/api/franchisee`, { - headers: { 'Access-Control-Allow-Origin': '*', Authorization: `Bearer ${token}` }, - }) - .then((res) => { - setLoading(false) - console.log(res.data.data) - setAllFranchisee(res.data.data) - }) - .catch((err) => { - setLoading(false) - // getBack() - }) - } - getProductDetails() - getFranchiseeDetails() - }, []) - - const handleChange = (e) => { - if (e.target.type === 'text') { - setData((prev) => ({ ...prev, [e.target.id]: e.target.value })) - } else { - setOrderStatus(e.target.value) - } - } - const handleQuantityChange = (e) => { - - setData((prev) => ({ - ...prev, - quantity: e.target.value, - total_Price: (productDetails?.base_Price * e.target.value) - })) - - } - - // ------------------------Frenchisee handle------------------------------// - - const handleGetSingleFrenchisee = async () => { - console.log(getFranchiseeID.current.value) - - axios - .get(`/api/franchisee/arrayspopulate/${getFranchiseeID.current.value}`, { - headers: { - 'Access-Control-Allow-Origin': '*', - Authorization: `Bearer ${token}`, - }, - }) - .then((res) => { - setLoading(false) - console.log(res.data.data) - let options = { - Franchisee: res?.data?.data?._id, - name: res?.data?.data?.name, - - - contact_Number: res?.data?.data?.contact_Number, - contact_Person_Name: res?.data?.data?.contact_Person_Name, - address: (res?.data?.data?.address_line_1 + ' ' + res?.data?.data?.address_line_2), - city: res?.data?.data?.city?.city_name, - price_Lable: res?.data?.data?.price_Lable, - state: res?.data?.data?.city?.state?.state_name, - banner: res?.data?.data?.banner?.url, - Franchisee_Url: res?.data?.data?.url - } - - dispatch({ type: "addShippingInfo", payload: options }); - - // localStorage.setItem("shippingInfo", JSON.stringify(AllStates.shipingInfo)); - - toast.success("Franchisee Added"); - - }) - .catch((err) => { - setLoading(false) - - }) - } - const FranchiseeRemove = (id) => { - dispatch({ - type: "deleteFromshippingInfo", - payload: { Franchisee: id }, - }); - toast.success("Franchisee Removed"); - + const [productDetails, setProductDetails] = useState(); + const [loading, setLoading] = useState(true); + const [orderStatus, setOrderStatus] = useState(""); + const [data, setData] = useState({ + product_Name: "", + address: "", + quantity: "", + contact_Number: "", + total_Price: "", + }); + useEffect(() => { + const getAllTax = async () => { + const res = await axios.get(`/api/tax/view_tax`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }); + if (res.data) { + // console.log(res.data) + setAllTax(res.data); + } }; - // ------------------------Frenchisee handle End------------------------------// - // ------------------------product handle------------------------------// + getAllTax(); + }, [token]); - const handleGetSingleProduct = async (e) => { - - - axios - .get(`/api/product/getOne/${getValue.current.value}`, { - headers: { 'Access-Control-Allow-Origin': '*', Authorization: `Bearer ${token}` }, - }) - .then((res) => { - setLoading(false) - const productAllkey = Object.keys(res?.data?.product); - const productAllValue = Object.values(res?.data?.product); - const findIndex1 = (productAllkey.indexOf(shipingInfo?.price_Lable)) - const findIndex2 = (productAllkey.indexOf(`${shipingInfo?.price_Lable}_With_Tax`)) - - - - let options = { - name: res?.data?.product?.name, - price: productAllValue[findIndex1], - product: res?.data?.product?._id, - quantity: 1, - - image: res?.data?.product?.image?.url, - - taxId: res?.data?.product?.taxId, - price_With_Tax: productAllValue[findIndex2], - } - dispatch({ type: "addToCart", payload: options }); - - dispatch({ type: "calculatePrice" }); - - toast.success("Product Added"); - - }) - .catch((err) => { - setLoading(false) - - }) + useEffect(() => { + function getProductDetails() { + setLoading(true); + axios + .get(`/api/product/getAll/admin`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + setLoading(false); + // console.log(res.data.product) + setProductData(res.data.product); + }) + .catch((err) => { + setLoading(false); + // getBack() + }); } - - - const handleRemove = (id) => { - dispatch({ - type: "deleteFromCart", - payload: { product: id }, + function getFranchiseeDetails() { + setLoading(true); + axios + .get(`/api/franchisee`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + setLoading(false); + console.log(res.data.data); + setAllFranchisee(res.data.data); + }) + .catch((err) => { + setLoading(false); + // getBack() }); - dispatch({ type: "calculatePrice" }); - toast.success("Item Removed"); - - }; - //increase qty - const increaseQuantity = (id) => { - - dispatch({ - type: "addToCart", - payload: { product: id }, - }); - dispatch({ type: "calculatePrice" }); - // localStorage.setItem("cartItems", JSON.stringify(AllStates.cart)); - } + getProductDetails(); + getFranchiseeDetails(); + }, []); + const handleChange = (e) => { + if (e.target.type === "text") { + setData((prev) => ({ ...prev, [e.target.id]: e.target.value })); + } else { + setOrderStatus(e.target.value); + } + }; + const handleQuantityChange = (e) => { + setData((prev) => ({ + ...prev, + quantity: e.target.value, + total_Price: productDetails?.base_Price * e.target.value, + })); + }; - const decreaseQuantity = (id) => { + // ------------------------Frenchisee handle------------------------------// - dispatch({ - type: "decrement", - payload: { product: id }, - }); + const handleGetSingleFrenchisee = async () => { + console.log(getFranchiseeID.current.value); + + axios + .get(`/api/franchisee/arrayspopulate/${getFranchiseeID.current.value}`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + setLoading(false); + console.log(res.data.data); + let options = { + Franchisee: res?.data?.data?._id, + name: res?.data?.data?.name, + + contact_Number: res?.data?.data?.contact_Number, + contact_Person_Name: res?.data?.data?.contact_Person_Name, + address: + res?.data?.data?.address_line_1 + + " " + + res?.data?.data?.address_line_2, + city: res?.data?.data?.city?.city_name, + price_Lable: res?.data?.data?.price_Lable, + state: res?.data?.data?.city?.state?.state_name, + banner: res?.data?.data?.banner?.url, + Franchisee_Url: res?.data?.data?.url, + }; + + dispatch({ type: "addShippingInfo", payload: options }); + + // localStorage.setItem("shippingInfo", JSON.stringify(AllStates.shipingInfo)); + + toast.success("Franchisee Added"); + }) + .catch((err) => { + setLoading(false); + }); + }; + const FranchiseeRemove = (id) => { + dispatch({ + type: "deleteFromshippingInfo", + payload: { Franchisee: id }, + }); + toast.success("Franchisee Removed"); + }; + // ------------------------Frenchisee handle End------------------------------// + // ------------------------product handle------------------------------// + + const handleGetSingleProduct = async (e) => { + axios + .get(`/api/product/getOne/${getValue.current.value}`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + setLoading(false); + const productAllkey = Object.keys(res?.data?.product); + const productAllValue = Object.values(res?.data?.product); + const findIndex1 = productAllkey.indexOf(shipingInfo?.price_Lable); + const findIndex2 = productAllkey.indexOf( + `${shipingInfo?.price_Lable}_With_Tax` + ); + + let options = { + name: res?.data?.product?.name, + price: productAllValue[findIndex1], + product: res?.data?.product?._id, + quantity: 1, + + image: res?.data?.product?.image?.url, + + taxId: res?.data?.product?.taxId, + price_With_Tax: productAllValue[findIndex2], + }; + dispatch({ type: "addToCart", payload: options }); dispatch({ type: "calculatePrice" }); - }; - // ------------------------product handle End------------------------------// + toast.success("Product Added"); + }) + .catch((err) => { + setLoading(false); + }); + }; + const handleRemove = (id) => { + dispatch({ + type: "deleteFromCart", + payload: { product: id }, + }); + dispatch({ type: "calculatePrice" }); + toast.success("Item Removed"); + }; + //increase qty + const increaseQuantity = (id) => { + dispatch({ + type: "addToCart", + payload: { product: id }, + }); + dispatch({ type: "calculatePrice" }); + // localStorage.setItem("cartItems", JSON.stringify(AllStates.cart)); + }; - function handleSubmit() { - if ( - shipingInfo === null) { - swal({ - title: 'Warning', - text: 'Please select Franchisee ', - icon: 'error', - button: 'Close', - dangerMode: true, - }) - return - } + const decreaseQuantity = (id) => { + dispatch({ + type: "decrement", + payload: { product: id }, + }); - else if (cartItems.length < 1) { - swal({ - title: 'Warning', - text: 'Please select atleast one product', - icon: 'error', - button: 'Close', - dangerMode: true, - }) - return - } + dispatch({ type: "calculatePrice" }); + }; + // ------------------------product handle End------------------------------// - - else if ( - tax === '' || - shippingCharge === '' || - total === '' - - ) { - swal({ - title: 'Warning', - text: 'Fill all mandatory fields', - icon: 'error', - button: 'Close', - dangerMode: true, - }) - return - } - - - - setLoading(true) - - - - - setLoading(true) - axios - .post( - `/api/order/create`, - { - orderItems: cartItems, - shippingInfo: shipingInfo, - shipping_charge: shippingCharge, - tax_amount: tax, - total_amount: total - - - }, - - { - headers: { - 'Access-Control-Allow-Origin': '*', - Authorization: `Bearer ${token}`, - }, - }, - ) - .then((res) => { - // console.log(res) - swal({ - title: 'Created', - text: res.data.message ? res.data.message : 'Order created!', - icon: 'success', - button: 'ok', - }) - setLoading(false) - navigate('/orders/new') - }) - .catch((error) => { - setLoading(false) - swal({ - title: 'Warning', - text: error.response.data.message ? error.response.data.message : 'Something went wrong!', - icon: 'error', - button: 'Retry', - dangerMode: true, - }) - }) + function handleSubmit() { + if (shipingInfo === null) { + swal({ + title: "Warning", + text: "Please select Franchisee ", + icon: "error", + button: "Close", + dangerMode: true, + }); + return; + } else if (cartItems.length < 1) { + swal({ + title: "Warning", + text: "Please select atleast one product", + icon: "error", + button: "Close", + dangerMode: true, + }); + return; + } else if (tax === "" || shippingCharge === "" || total === "") { + swal({ + title: "Warning", + text: "Fill all mandatory fields", + icon: "error", + button: "Close", + dangerMode: true, + }); + return; } + setLoading(true); - function getBack() { - navigate(`/orders/${status}`, { replace: true }) - } + setLoading(true); + axios + .post( + `/api/order/create`, + { + orderItems: cartItems, + shippingInfo: shipingInfo, + shipping_charge: shippingCharge, + tax_amount: tax, + total_amount: total, + }, - return ( - <> - {' '} -
    -
    -
    -
    -
    -
    { + // console.log(res) + swal({ + title: "Created", + text: res.data.message ? res.data.message : "Order created!", + icon: "success", + button: "ok", + }); + setLoading(false); + navigate("/orders/new"); + }) + .catch((error) => { + setLoading(false); + swal({ + title: "Warning", + text: error.response.data.message + ? error.response.data.message + : "Something went wrong!", + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + } + + function getBack() { + navigate(`/orders/${status}`, { replace: true }); + } + + return ( + <> + {" "} +
    +
    +
    +
    +
    +
    -
    - Add Order -
    -
    - - - - -
    - -
    - -
    -
    - - -
    -
    -
    -
    -
    - -
    - - -
    - - -
    - - - { - shipingInfo !== null && -
    -
    -
    - {shipingInfo?.name} -
    -
    -
    {shipingInfo?.name}
    - - Address. : {shipingInfo?.address} - -

    - Contact No. : {shipingInfo?.contact_Number} -

    -

    - Contact Person Name : {shipingInfo?.contact_Person_Name} -

    -

    - Price Lable : {shipingInfo?.price_Lable} -

    - - - - - - - - -
    -
    -
    - -
    - } - -
    - -
    {' '} -
    - -
    -
    -
    - - -
    -
    - - {shipingInfo !== null &&
    -
    -
    - -
    - - - -
    - -
    - -
    - - - { - cartItems && cartItems.map((productDetails, i) => -
    -
    -
    - {productDetails?.name} -
    -
    -
    {productDetails?.name}
    -
    -
    - - -
    - - {productDetails?.quantity} - - -
    - -

    - Price With Tax: ₹{productDetails?.price_With_Tax} -

    - -
    -
    -

    - Price: ₹{productDetails?.price} -

    - - - - -
    -
    -
    -
    -
    - -
    - ) - } - {subTotal &&
    - Total Order Value: ₹{subTotal} -
    } -
    -
    -
    - - } - - - - - - - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Order Placed On : - {productData?.status_timeline?.new - ? new Date(productData?.status_timeline?.new).toLocaleString('en-IN', { - month: 'short', - day: 'numeric', - year: 'numeric', - hour: '2-digit', - minute: 'numeric', - hour12: true, - }) - : new Date(productData?.placed_on).toLocaleString('en-IN', { - month: 'short', - day: 'numeric', - year: 'numeric', - hour: '2-digit', - minute: 'numeric', - hour12: true, - })} -
    Processing Started : - {productData?.status_timeline?.processing - ? new Date(productData?.status_timeline?.processing).toLocaleString( - 'en-IN', - { - month: 'short', - day: 'numeric', - year: 'numeric', - hour: '2-digit', - minute: 'numeric', - hour12: true, - }, - ) - : '-'} -
    Dispatched On : - {productData?.status_timeline?.dispatched - ? new Date(productData?.status_timeline?.dispatched).toLocaleString( - 'en-IN', - { - month: 'short', - day: 'numeric', - year: 'numeric', - hour: '2-digit', - minute: 'numeric', - hour12: true, - }, - ) - : '-'} -
    Delivered On : - {productData?.status_timeline?.delivered - ? new Date(productData?.status_timeline?.delivered).toLocaleString( - 'en-IN', - { - month: 'short', - day: 'numeric', - year: 'numeric', - hour: '2-digit', - minute: 'numeric', - hour12: true, - }, - ) - : '-'} -
    Cancelled On : - {productData?.status_timeline?.cancelled - ? new Date(productData?.status_timeline?.cancelled).toLocaleString( - 'en-IN', - { - month: 'short', - day: 'numeric', - year: 'numeric', - hour: '2-digit', - minute: 'numeric', - hour12: true, - }, - ) - : '-'} -
    Returned On : - {productData?.status_timeline?.returned - ? new Date(productData?.status_timeline?.returned).toLocaleString( - 'en-IN', - { - month: 'short', - day: 'numeric', - year: 'numeric', - hour: '2-digit', - minute: 'numeric', - hour12: true, - }, - ) - : '-'} -
    -
    -
    - - - - - - -
    -
    -
    + > +
    + Add Order +
    +
    + + + + +
    +
    -
    - {/* */} + +
    +
    +
    +
    +
    + +
    + + +
    +
    + {shipingInfo !== null && ( +
    +
    +
    + {shipingInfo?.name} +
    +
    +
    {shipingInfo?.name}
    + + Address. : {shipingInfo?.address} + +

    + Contact No. : {shipingInfo?.contact_Number} +

    +

    + Contact Person Name :{" "} + {shipingInfo?.contact_Person_Name} +

    +

    + Price Lable : {shipingInfo?.price_Lable} +

    + + +
    +
    +
    +
    + )} +
    + +
    {" "} +
    + +
    +
    +
    +
    +
    + {shipingInfo !== null && ( +
    +
    +
    + +
    + + +
    +
    + +
    + + + {cartItems && + cartItems.map((productDetails, i) => ( +
    +
    +
    + {productDetails?.name} +
    +
    +
    + {productDetails?.name} +
    +
    +
    +
    + + + {productDetails?.quantity} + + +
    + +

    + Price With Tax: ₹ + {productDetails?.price_With_Tax} +

    + +
    +
    +

    + Price: ₹ + {productDetails?.price} +

    +
    +
    +
    +
    +
    +
    + ))} + {subTotal && ( +
    + Total Order Value: ₹{subTotal} +
    + )} +
    +
    +
    + )} + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Order Placed On : + {productData?.status_timeline?.new + ? new Date( + productData?.status_timeline?.new + ).toLocaleString("en-IN", { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + }) + : new Date(productData?.placed_on).toLocaleString( + "en-IN", + { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + } + )} +
    Processing Started : + {productData?.status_timeline?.processing + ? new Date( + productData?.status_timeline?.processing + ).toLocaleString("en-IN", { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + }) + : "-"} +
    Dispatched On : + {productData?.status_timeline?.dispatched + ? new Date( + productData?.status_timeline?.dispatched + ).toLocaleString("en-IN", { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + }) + : "-"} +
    Delivered On : + {productData?.status_timeline?.delivered + ? new Date( + productData?.status_timeline?.delivered + ).toLocaleString("en-IN", { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + }) + : "-"} +
    Cancelled On : + {productData?.status_timeline?.cancelled + ? new Date( + productData?.status_timeline?.cancelled + ).toLocaleString("en-IN", { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + }) + : "-"} +
    Returned On : + {productData?.status_timeline?.returned + ? new Date( + productData?.status_timeline?.returned + ).toLocaleString("en-IN", { + month: "short", + day: "numeric", + year: "numeric", + hour: "2-digit", + minute: "numeric", + hour12: true, + }) + : "-"} +
    +
    +
    +
    - - ) +
    +
    +
    +
    + {/* */} +
    + + ); } -export default AddOrder +export default AddOrder; diff --git a/src/views/orders/EditOrder.js b/src/views/orders/EditOrder.js index 1b5d147..9622c32 100644 --- a/src/views/orders/EditOrder.js +++ b/src/views/orders/EditOrder.js @@ -93,7 +93,7 @@ function EditOrder() { function getProductDetails() { setLoading(true); axios - .get(`/api/product/getAll/`, { + .get(`/api/product/getAll/admin`, { headers: { "Access-Control-Allow-Origin": "*", Authorization: `Bearer ${token}`, diff --git a/src/views/pages/login/Login.js b/src/views/pages/login/Login.js index 46f1cbe..d0e09ca 100644 --- a/src/views/pages/login/Login.js +++ b/src/views/pages/login/Login.js @@ -100,8 +100,10 @@ const Login = () => { setLoading({ loading: true }); try { const res = await axios.post("/api/v1/user/login/", auth); + console.log(res); if (res.data.success == true) { localStorage.setItem("authToken", res.data.token); + let response = await axios.get(`/api/v1/user/details`, { headers: { Authorization: `Bearer ${res.data.token}`, @@ -109,7 +111,7 @@ const Login = () => { }); // console.log(response.data) const data = response.data; - if (data.user.role === "admin") { + if (data.user.role === "admin" || data.user.role === "Employee") { history("/dashboard"); setLoading(false); window.location.reload();