From 6bce3a40837c7c2f1310151cadd5976146349103 Mon Sep 17 00:00:00 2001 From: ROSHAN GARG Date: Sat, 2 Nov 2024 11:58:00 +0530 Subject: [PATCH] integration is done --- src/_nav.js | 14 +- src/routes.js | 9 + src/views/Transporter/Transporter.js | 537 +++++++++++++++++++++++++++ src/views/orders/ViewOrders.js | 32 +- src/views/orders/viewInoices.js | 103 +++-- 5 files changed, 642 insertions(+), 53 deletions(-) create mode 100644 src/views/Transporter/Transporter.js diff --git a/src/_nav.js b/src/_nav.js index 0d3c9ca..2e52e46 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -248,13 +248,13 @@ const _nav = [ group: "", items: [ - // { - // component: CNavItem, - // name: "Testimonials", - // icon: , - // to: "/testimonials", - // group: "Website Related", - // }, + { + component: CNavItem, + name: "Transporter", + icon: , + to: "/transporter", + group: "Transporter", + }, // { // component: CNavItem, diff --git a/src/routes.js b/src/routes.js index fedd951..0c43088 100644 --- a/src/routes.js +++ b/src/routes.js @@ -169,6 +169,7 @@ import DistributorOpeningInventory from "./views/PrincipalDistributors/OpeningIn import UploadOpeningInventory from "./views/PrincipalDistributors/UploadOpeningInventory"; import OpeningInventoryReports from "./views/Reports/OpeningInventoryReports"; import StockReports from "./views/Reports/StockReports "; +import Transporter from "./views/Transporter/Transporter"; const routes = [ //dashboard @@ -930,6 +931,14 @@ const routes = [ element: EditEmployee, navName: "Employees & Access", }, + + // Transporter + { + path: "transporter", + name: "Transporter", + element: Transporter, + navName: "Employees & Access", + }, ]; export default routes; diff --git a/src/views/Transporter/Transporter.js b/src/views/Transporter/Transporter.js new file mode 100644 index 0000000..a52622b --- /dev/null +++ b/src/views/Transporter/Transporter.js @@ -0,0 +1,537 @@ +import React, { useState, useEffect, useRef, useCallback } from "react"; +import axios from "axios"; +import { isAutheticated } from "src/auth"; +import { + Button, + Box, + IconButton, + Modal, + Pagination, + TextField, + Typography, +} from "@mui/material"; +import CloseIcon from "@mui/icons-material/Close"; +import { ClipLoader } from "react-spinners"; +import swal from "sweetalert"; +import { toast } from "react-hot-toast"; +import debounce from "lodash.debounce"; +const style = { + position: "absolute", + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + width: 400, + bgcolor: "background.paper", + borderRadius: "0.5rem", + boxShadow: 24, + width: "500px", +}; + +const Transporter = () => { + const token = isAutheticated(); + const nameRef = useRef(); + const [loading, setLoading] = useState(true); + const [updating, setUpdating] = useState(true); + const [saveLoding, setSaveLoading] = useState(true); + const [edit, setEdit] = useState(false); + const [transporterName, settransporterName] = useState(""); + const [categoryId, setCategoryId] = useState(""); + const [transporter, setTransporter] = useState([]); + const [itemPerPage, setItemPerPage] = useState(10); + const [page, setPage] = useState(1); + const [open, setOpen] = useState(false); + const [oldertransporterName, setOlderCategoruName] = useState(""); + + const handleOpen = () => setOpen(true); + const handleClose = () => { + setOpen(false); + // setUpdating(false); + setEdit(false); + + settransporterName(""); + setCategoryId(""); + }; + + const getCategories = async () => { + try { + setLoading(true); + const response = await axios.get("/api/transporter/get", { + headers: { + Authorization: `Bearer ${token}`, + }, // Include pagination and search + }); + + if (response.status === 200) { + setTransporter(response?.data?.transporters); + } + } catch (error) { + console.error("Failed to fetch brands:", error); + } finally { + setLoading(false); // Set loading to false after fetching + } + }; + + useEffect(() => { + getCategories(); + }, []); + + const handleEditClick = (_id, transporterName) => { + setOpen(true); + settransporterName(transporterName); + setCategoryId(_id); + setOlderCategoruName(transporterName); + setEdit(true); + // setUpdating(false); + }; + + const handleUpdate = async () => { + const filteredArrayNames = transporter + .filter( + (item) => + item.transporterName.toLowerCase() !== + oldertransporterName.toLowerCase() + ) + .map((item) => item.transporterName.toLowerCase()); + // console.log(filteredArrayNames, "filter"); + if (filteredArrayNames.includes(transporterName.toLowerCase())) { + swal({ + title: "Warning", + text: "Transporter name already exists ", + icon: "error", + button: "Retry", + dangerMode: true, + }); + } + if (!transporterName) { + swal({ + title: "Warning", + text: "Please fill all the required fields!", + icon: "error", + button: "Retry", + dangerMode: true, + }); + return; + } + setUpdating(false); + const formData = new FormData(); + formData.append("transporterName", transporterName); + try { + await axios.patch(`/api/transporter/edit/${categoryId}`, formData, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + handleClose(); + toast.success("Transporter updated successfully"); + getCategories(); + } catch (err) { + swal({ + title: "", + text: "Something went wrong!", + icon: "error", + button: "Retry", + dangerMode: true, + }); + } finally { + setUpdating(true); + } + }; + + const handleDelete = (_id) => { + swal({ + title: "Are you sure?", + icon: "error", + buttons: { + Yes: { text: "Yes", value: true }, + Cancel: { text: "Cancel", value: "cancel" }, + }, + }).then(async (value) => { + if (value === true) { + try { + await axios.delete(`/api/transporter/delete/${_id}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + toast.success("Transporter deleted successfully"); + getCategories(); + } catch (err) { + swal({ + title: "", + text: "Something went wrong!", + icon: "error", + button: "Retry", + dangerMode: true, + }); + } + } + }); + }; + + const handleSaveCategory = async () => { + if ( + transporter.some( + (item) => + item.transporterName.toLowerCase() === transporterName.toLowerCase() + ) + ) { + swal({ + title: "Warning", + text: "Category already exists ", + icon: "error", + button: "Retry", + dangerMode: true, + }); + return; + } + if (!transporterName) { + swal({ + title: "Warning", + text: "Please fill all the required fields!", + icon: "error", + button: "Retry", + dangerMode: true, + }); + return; + } + setSaveLoading(false); + setLoading(true); + const formData = new FormData(); + formData.append("transporterName", transporterName); + try { + await axios.post("/api/transporter/add", formData, { + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "multipart/formdata", + }, + }); + handleClose(); + toast.success("Transpoter added successfully"); + getCategories(); + } catch (err) { + swal({ + title: "", + text: "Something went wrong!", + icon: "error", + button: "Retry", + dangerMode: true, + }); + } finally { + setSaveLoading(true); + } + }; + const getPageCount = () => { + return Math.max(1, Math.ceil(transporter.length / itemPerPage)); + }; + const debouncedSearch = useCallback( + debounce(() => { + setPage(1); + getCategories(); + }, 500), + [] + ); + + const handleSearchChange = () => { + debouncedSearch(); + }; + return ( +
+
+
+
+
+
+
+ Transporter +
+ +
+ + + + + + Transporter name + + handleClose()}> + + + +
+ + settransporterName( + e.target.value.charAt(0).toUpperCase() + + e.target.value.slice(1) + ) + } + /> + {transporterName ? ( + <> + + {25 - transporterName.length} characters left + + + ) : ( + <> + )} + + + {!edit && ( + + )} + {edit && ( + + )} + + +
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+ {/*
+ + +
*/} +
+ +
+ + + + + + + + + + {!loading && transporter.length === 0 && ( + + + + )} + {loading ? ( + + + + ) : ( + transporter && + transporter + .slice( + (`${page}` - 1) * itemPerPage, + `${page}` * itemPerPage + ) + .map((item, i) => ( + + + + + )) + )} + +
Transporter NameAction
+
No Data Available
+
+ Loading... +
+
{item.transporterName}
+
+ + +
+
+ +
+ setPage(value)} + /> +
+
+
+
+
+
+
+
+ ); +}; + +export default Transporter; diff --git a/src/views/orders/ViewOrders.js b/src/views/orders/ViewOrders.js index 5caec2d..bde6f35 100644 --- a/src/views/orders/ViewOrders.js +++ b/src/views/orders/ViewOrders.js @@ -17,7 +17,10 @@ import { DialogContentText, DialogTitle, TextField, - Divider, InputLabel, Select, MenuItem + Divider, + InputLabel, + Select, + MenuItem, } from "@mui/material"; import onvoicesData from "../../assets/incoicedata.json"; import { useNavigate, useParams } from "react-router-dom"; @@ -340,8 +343,8 @@ const ViewOrders = () => { {item?.name} { }} /> - {item?.name} + {item.productId.name} - ₹{item.price.toFixed(2)} - {item.quantity} - ₹{subtotal.toFixed(2)} + ₹{item.price} + + {item.quantity} + + ₹{subtotal} {item.GST}% - ₹{gstAmount.toFixed(2)} - ₹{totalWithGST.toFixed(2)} + ₹{gstAmount} + ₹{totalWithGST} ); })} @@ -370,7 +375,8 @@ const ViewOrders = () => { <> {" "} - Order Items {order?.status=="pending"?"to be Processed":"Cancelled"} + Order Items{" "} + {order?.status == "pending" ? "to be Processed" : "Cancelled"} @@ -394,10 +400,10 @@ const ViewOrders = () => { Total Items: {order?.orderItem.length} - Total Subtotal: ₹{order?.subtotal.toFixed(2)} - Total GST: ₹{order?.gstTotal.toFixed(2)} + Total Subtotal: ₹{order?.subtotal} + Total GST: ₹{order?.gstTotal} - Grand Total: ₹{order?.grandTotal.toFixed(2)} + Grand Total: ₹{order?.grandTotal} diff --git a/src/views/orders/viewInoices.js b/src/views/orders/viewInoices.js index 9a3a92d..97ad16b 100644 --- a/src/views/orders/viewInoices.js +++ b/src/views/orders/viewInoices.js @@ -19,6 +19,9 @@ import { TextField, Divider, Chip, + InputLabel, + Select, + MenuItem, } from "@mui/material"; import onvoicesData from "../../assets/incoicedata.json"; import { useNavigate, useParams } from "react-router-dom"; @@ -58,7 +61,7 @@ const ViewInvoices = () => { Authorization: `Bearer ${token}`, }, }); - // console.log(response); + console.log(response); setInvoice(response.data); setStatus(response.data.courierStatus); @@ -139,6 +142,31 @@ const ViewInvoices = () => { setOpenDispatchDialog(false); setOpenDeliveredDialog(false); // Close delivered dialog }; + const [transporterName, setTransporterName] = useState(""); + const [transporter, setTransporter] = useState([]); + // Get order ID from URL params + const getCategories = async () => { + try { + setLoading(true); + const response = await axios.get("/api/transporter/get", { + headers: { + Authorization: `Bearer ${token}`, + }, // Include pagination and search + }); + + if (response.status === 200) { + setTransporter(response?.data?.transporters); + } + } catch (error) { + console.error("Failed to fetch brands:", error); + } finally { + setLoading(false); // Set loading to false after fetching + } + }; + + useEffect(() => { + getCategories(); + }, []); if (loading) { return Loading...; @@ -188,27 +216,27 @@ const ViewInvoices = () => { - - {invoice.invoiceId} + + {invoice?.invoiceId} - {invoice.items.map((item) => ( + {invoice?.items?.map((item) => (
- {item.name} ({item.SKU}) x{" "} - {item.processquantity} + {item?.name} ({item?.SKU}) x{" "} + {item?.processquantity}
))}
- ₹{invoice.subtotal.toFixed(2)} - ₹{invoice.gstTotal.toFixed(2)} - ₹{invoice.invoiceAmount.toFixed(2)} + ₹{invoice?.subtotal.toFixed(2)} + ₹{invoice?.gstTotal.toFixed(2)} + ₹{invoice?.invoiceAmount.toFixed(2)} { Total Items: {invoice?.items.length} Total Subtotal: ₹{invoice?.subtotal} - Total GST: ₹{invoice?.gstTotal} + + Total GST: ₹{invoice?.gstTotal.toFixed(2)} + Grand Total: ₹{invoice?.invoiceAmount} @@ -431,28 +461,35 @@ const ViewInvoices = () => {
- Please provide courier name and ID for dispatch: + Please provide the transporter name: - setCourierName(e.target.value)} - /> - setCourierId(e.target.value)} - /> + + Transporter Name + +