rd order show in admin

This commit is contained in:
Sibunnayak 2025-02-08 17:52:25 +05:30
parent 1d5de2e4a4
commit 64c927f27b
8 changed files with 567 additions and 21 deletions

View File

@ -234,6 +234,13 @@ const _nav = [
// }, // },
], ],
}, },
{
component: CNavItem,
name: "Retailer Orders",
icon: <CIcon icon={cilCart} customClassName="nav-icon" />,
to: "/retailer/order",
group: "RetailerOrders",
},
{ {
component: CNavItem, component: CNavItem,
name: "Announcement", name: "Announcement",

View File

@ -177,6 +177,8 @@ import SingleUserTask from "./views/Tasks/SingleUserTask";
import Tasks from "./views/Tasks/Task"; import Tasks from "./views/Tasks/Task";
import DistributorLiqudations from "./views/PrincipalDistributors/DistributorLiqudation"; import DistributorLiqudations from "./views/PrincipalDistributors/DistributorLiqudation";
import UpdatePrincipalDistributor from "./views/PrincipalDistributors/updateprincipaldistributor"; import UpdatePrincipalDistributor from "./views/PrincipalDistributors/updateprincipaldistributor";
import RDViewOrder from "./views/RetailerOrders/ViewOrder";
import RetailerOrder from "./views/RetailerOrders/RetailerOrder";
const routes = [ const routes = [
//dashboard //dashboard
@ -821,6 +823,19 @@ const routes = [
element: InStoreQRCodeOrders, element: InStoreQRCodeOrders,
navName: "Orders", navName: "Orders",
}, },
// -------------RD ORDER------------
{
path: "/rdorders/view/:id",
name: "View Order",
element: RDViewOrder,
navName: "RetailerOrders",
},
{
path: "/retailer/order",
name: "Retaioler Order",
element: RetailerOrder,
navName: "RetailerOrders",
},
//-------------- End Order Management Routes--------------------------------------- //-------------- End Order Management Routes---------------------------------------
// Announcement // Announcement
{ {

View File

@ -444,17 +444,19 @@ const SingleDistributorOrder = () => {
return ( return (
<TableRow key={index}> <TableRow key={index}>
<TableCell> <TableCell>
<img {item.image.length > 0 && (
src={item.productId.image} <img
alt={item.productId.name} src={item?.image[0]?.url}
style={{ alt={item.name}
width: 50, style={{
height: 50, width: 50,
marginRight: 10, height: 50,
}} marginRight: 10,
/> }}
/>
)}
<Typography variant="subtitle1"> <Typography variant="subtitle1">
{item.productId.name} {item.name}
</Typography> </Typography>
</TableCell> </TableCell>
<TableCell align="right">{item.price}</TableCell> <TableCell align="right">{item.price}</TableCell>

View File

@ -132,9 +132,7 @@ const RetailDistributor = () => {
); );
if (response.data.success) { if (response.data.success) {
toast.success( toast.success("Password reset successfully! Email sent to Retailer.");
"Password reset successfully! Email sent to Retailer."
);
} }
} catch (error) { } catch (error) {
toast.error( toast.error(
@ -464,7 +462,7 @@ const RetailDistributor = () => {
Previous Previous
</a> </a>
</li> </li>
{Array.from({ length: totalPages }, (_, index) => ( {/* {Array.from({ length: totalPages }, (_, index) => (
<li <li
key={index} key={index}
className={`paginate_button page-item ${ className={`paginate_button page-item ${
@ -479,7 +477,38 @@ const RetailDistributor = () => {
{index + 1} {index + 1}
</a> </a>
</li> </li>
))} ))} */}
{Array.from(
{ length: Math.min(3, totalPages) },
(_, index) => {
let page = currentPage;
// Adjust start page to keep current page centered if possible
if (totalPages > 3) {
if (currentPage === 1) page = 1;
else if (currentPage === totalPages)
page = totalPages - 2;
else page = currentPage - 1;
}
return (
<li
key={index}
className={`paginate_button page-item ${
currentPage === page + index ? "active" : ""
}`}
>
<a
className="page-link"
onClick={() => setCurrentPage(page + index)}
aria-controls="datatable"
>
{page + index}
</a>
</li>
);
}
)}
<li <li
className={`paginate_button page-item next ${ className={`paginate_button page-item next ${
currentPage === totalPages ? "disabled" : "" currentPage === totalPages ? "disabled" : ""

View File

@ -0,0 +1,202 @@
import React, { useState, useEffect } from "react";
import {
Box,
Button,
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Typography,
TablePagination,
TextField,
MenuItem,
FormControl,
InputLabel,
Select,
Skeleton,
} from "@mui/material";
import { useNavigate } from "react-router-dom";
import axios from "axios";
import { isAutheticated } from "src/auth";
import { debounce } from "lodash"; // Import lodash debounce
const RetailerOrder = () => {
const [orders, setOrders] = useState([]);
const [loading, setLoading] = useState(true);
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5);
const [totalOrders, setTotalOrders] = useState(0);
const [searchField, setSearchField] = useState("retailer");
const [searchText, setSearchText] = useState("");
const navigate = useNavigate();
const token = isAutheticated();
// Fetch orders with pagination and search
const fetchOrders = async (page, limit, searchField, searchText) => {
setLoading(true);
try {
const response = await axios.get("/api/rd-order", {
headers: {
Authorization: `Bearer ${token}`,
},
params: {
page: page + 1, // Adjusting for zero-based index in the UI
limit,
searchField,
searchText,
},
});
setOrders(response?.data?.orders || []);
setTotalOrders(response?.data?.totalOrders || 0);
} catch (error) {
console.error("Error fetching orders:", error);
} finally {
setLoading(false);
}
};
// Debounce API calls when search text changes
const debouncedFetchOrders = debounce(
(page, limit, searchField, searchText) => {
fetchOrders(page, limit, searchField, searchText);
},
500
);
useEffect(() => {
debouncedFetchOrders(page, rowsPerPage, searchField, searchText);
return () => debouncedFetchOrders.cancel(); // Cleanup to avoid unnecessary calls
}, [page, rowsPerPage, searchField, searchText]);
const handleSearchChange = (event) => {
setSearchText(event.target.value);
setPage(0); // Reset to first page on search
};
const handleSearchFieldChange = (event) => {
setSearchField(event.target.value);
setSearchText(""); // Reset search text on field change
setPage(0); // Reset to first page on field change
};
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
return (
<Box>
<Typography variant="h4" mb={2} textAlign="center">
Retailer Order List
</Typography>
<Box display="flex" mb={2} alignItems="center">
<FormControl variant="outlined" sx={{ minWidth: 150, mr: 2 }}>
<InputLabel id="search-field-label">Search By</InputLabel>
<Select
labelId="search-field-label"
id="search-field"
value={searchField}
onChange={handleSearchFieldChange}
label="Search By"
>
<MenuItem value="Order ID">Order ID</MenuItem>
<MenuItem value="Status">Status</MenuItem>
<MenuItem value="retailer">Retailer Name</MenuItem>
</Select>
</FormControl>
<TextField
label={`Search by ${searchField}`}
variant="outlined"
value={searchText}
onChange={handleSearchChange}
fullWidth
/>
</Box>
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>Order ID</TableCell>
<TableCell>Retailer Name</TableCell>
<TableCell>Respected PD</TableCell>
<TableCell>Order Date</TableCell>
<TableCell>Items</TableCell>
<TableCell>Order Value</TableCell>
<TableCell>Status</TableCell>
<TableCell>Action</TableCell>
</TableRow>
</TableHead>
<TableBody>
{loading ? (
Array.from(new Array(rowsPerPage)).map((_, index) => (
<TableRow key={index}>
<TableCell colSpan={8}>
<Skeleton height={40} />
</TableCell>
</TableRow>
))
) : orders.length > 0 ? (
orders.map((order) => (
<TableRow key={order._id}>
<TableCell>{order.uniqueId}</TableCell>
<TableCell>{order.addedBy?.name || "N/A"}</TableCell>
<TableCell>{order.pd?.name || "N/A"}</TableCell>
<TableCell>
{new Date(order.createdAt).toDateString()}
<span>, {formatAMPM(order.createdAt)}</span>
</TableCell>
<TableCell>{order.orderItem.length}</TableCell>
<TableCell> {order.grandTotal.toFixed(2)}</TableCell>
<TableCell>{order.status}</TableCell>
<TableCell>
<Button
variant="contained"
color="primary"
onClick={() => navigate(`/rdorders/view/${order._id}`)}
>
View
</Button>
</TableCell>
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={8} align="center">
<Typography variant="body1">Data not found</Typography>
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
<TablePagination
rowsPerPageOptions={[5, 10, 25]}
component="div"
count={totalOrders}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</TableContainer>
</Box>
);
};
// Helper function to format time as AM/PM
const formatAMPM = (date) => {
var hours = new Date(date).getHours();
var minutes = new Date(date).getMinutes();
var ampm = hours >= 12 ? "PM" : "AM";
hours = hours % 12 || 12;
minutes = minutes < 10 ? "0" + minutes : minutes;
return `${hours}:${minutes} ${ampm}`;
};
export default RetailerOrder;

View File

@ -0,0 +1,287 @@
import React, { useState, useEffect } from "react";
import {
Box,
Typography,
Grid,
Button,
Table,
TableBody,
TableCell,
TableHead,
TableRow,
Paper,
Divider,
} from "@mui/material";
import { useNavigate, useParams } from "react-router-dom";
import { TableContainer } from "@material-ui/core";
import axios from "axios"; // Import axios for HTTP requests
import { isAutheticated } from "src/auth";
import InvoiceTable from "../orders/invoiceTable";
import PendingOrderTable from "../orders/pendingOrderTable";
const RDViewOrder = () => {
const [order, setOrder] = useState(null); // State to store order details
const token = isAutheticated(); // State for delivery date
const [loading, setLoading] = useState(true); // Loading state
const [error, setError] = useState(null); // Error state
const navigate = useNavigate();
const { id } = useParams();
// Get order ID from URL params
useEffect(() => {
const fetchOrderDetails = async () => {
try {
const response = await axios.get(
`/api/get-single-placed-order-rd/${id}`,
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
// console.log(response);
setOrder(response.data.singleOrder);
setLoading(false);
} catch (err) {
setError("Failed to fetch order details");
setLoading(false);
}
};
fetchOrderDetails();
}, [id]);
if (loading) {
return <Typography>Loading...</Typography>;
}
if (error) {
return <Typography color="error">{error}</Typography>;
}
return (
<Box>
<Box
display="flex"
justifyContent="space-between"
alignItems="center"
mb={5}
>
<Typography variant="h4" sx={{ flexGrow: 1, textAlign: "center" }}>
Order ID: {order?.uniqueId}
</Typography>
<Button
color="primary"
onClick={() => navigate(`/retailer/order`)}
variant="contained"
>
Back
</Button>
</Box>
<Grid container spacing={2}>
<Grid item md={8} xl={8} lg={8}>
<Box sx={{ padding: 2, background: "#fff" }}>
{order.invoices?.length > 0 && (
<>
<Typography variant="h4" gutterBottom>
Invoices
</Typography>
<InvoiceTable invoices={order.invoices} />
</>
)}
<Typography variant="h4" my={3} gutterBottom>
Order Summary
</Typography>
<Grid container spacing={2}>
<Grid item xs={12}>
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>Product</TableCell>
<TableCell align="right">Price ()</TableCell>
<TableCell align="right">Order Quantity</TableCell>
<TableCell align="right">Subtotal ()</TableCell>
<TableCell align="right">GST (%)</TableCell>
<TableCell align="right">GST Amount ()</TableCell>
<TableCell align="right">Total with GST ()</TableCell>
</TableRow>
</TableHead>
<TableBody>
{order?.orderItem.map((item, index) => {
const subtotal = item.price * item.quantity;
const gstAmount = (
((item.GST * item.price) / 100) *
item.quantity
).toFixed(2);
const totalWithGST = (
subtotal + parseFloat(gstAmount)
).toFixed(2);
return (
<TableRow key={index}>
<TableCell>
{item.image.length > 0 && (
<img
src={item?.image[0]?.url}
alt={item.name}
style={{
width: 50,
height: 50,
marginRight: 10,
}}
/>
)}
<Typography variant="subtitle1">
{item.name}
</Typography>
</TableCell>
<TableCell align="right">{item.price}</TableCell>
<TableCell align="center">
{item.quantity}
</TableCell>
<TableCell align="right">{subtotal}</TableCell>
<TableCell align="right">{item.GST}%</TableCell>
<TableCell align="right">{gstAmount}</TableCell>
<TableCell align="right">{totalWithGST}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
</Grid>
</Grid>
{order.invoices?.length > 0 && (
<>
{" "}
<Typography variant="h4" my={3} gutterBottom>
Order Items{" "}
{order?.status == "pending" ? "to be Processed" : "Cancelled"}
</Typography>
<PendingOrderTable order={order} />
</>
)}
<Grid container spacing={2}>
<Grid item sm={6} md={6} xl={6}>
<Box
sx={{
marginTop: 4,
padding: 2,
backgroundColor: "blue",
color: "white",
}}
>
<Typography variant="h5" gutterBottom>
Order Summary
</Typography>
<Divider sx={{ marginBottom: 2 }} />
<Typography>
Total Items: {order?.orderItem.length}
</Typography>
<Typography>Total Subtotal: {order?.subtotal}</Typography>
<Typography>Total GST: {order?.gstTotal}</Typography>
<Typography variant="h5" sx={{ marginTop: 2 }}>
Grand Total: {order?.grandTotal}
</Typography>
</Box>
</Grid>
</Grid>
</Box>
</Grid>
<Grid item md={4} xl={4} lg={4}>
<Box
sx={{
background: "#fff",
padding: "1rem",
borderRadius: "0.8rem",
}}
>
<Grid container spacing={2}>
<Grid item sm={12} md={12} lg={12}>
<Typography variant="h5" sx={{ mb: "0.5rem" }}>
Retailer Details
</Typography>
<Typography sx={{ mb: "0.5rem" }}>
<strong>SBU:</strong> {order?.addedBy.uniqueId}
</Typography>
<Typography sx={{ mb: "0.5rem" }}>
<strong>Name:</strong> {order?.addedBy.name}
</Typography>
<Typography sx={{ mb: "0.5rem" }}>
<strong>Email id:</strong> {order?.addedBy.email}
</Typography>
<Typography sx={{ mb: "0.5rem" }}>
<strong>Number:</strong> {order?.addedBy.mobile_number}
</Typography>
</Grid>
<Grid item sm={12} md={12} lg={12}>
<Typography variant="h5" sx={{ mb: "0.5rem" }}>
Respected PD Details
</Typography>
<Typography sx={{ mb: "0.5rem" }}>
<strong>SBU:</strong> {order?.pd.SBU}
</Typography>
<Typography sx={{ mb: "0.5rem" }}>
<strong>Name:</strong> {order?.pd.name}
</Typography>
<Typography sx={{ mb: "0.5rem" }}>
<strong>Email id:</strong> {order?.pd.email}
</Typography>
<Typography sx={{ mb: "0.5rem" }}>
<strong>Number:</strong> {order?.pd.phone}
</Typography>
</Grid>
<Grid item sm={6} md={6} lg={6}>
<Typography variant="h5" sx={{ mb: "0.5rem" }}>
Bill Address
</Typography>
<Typography sx={{ mb: "0.5rem" }}>{order?.billTo}</Typography>
</Grid>
<Grid item sm={6} md={6} lg={6}>
<Typography variant="h5" sx={{ mb: "0.5rem" }}>
Ship Address
</Typography>
<Typography sx={{ mb: "0.5rem" }}>{order?.shipTo}</Typography>
</Grid>
<Grid item sm={6} md={6} lg={6}>
<Typography variant="h5" sx={{ mb: "0.5rem" }}>
Payment mode
</Typography>
<Typography sx={{ mb: "0.5rem" }}>
{order?.paymentMode}
</Typography>
</Grid>
<Grid item sm={12} md={12} lg={12}>
<Typography variant="h5" sx={{ mb: "0.5rem" }}>
Order Status
</Typography>
<Typography sx={{ mb: "0.5rem" }}>{order?.status}</Typography>
{order?.status === "cancelled" && (
<Typography sx={{ mb: "0.5rem", color: "red" }}>
{order?.order_Cancelled_Reason}
</Typography>
)}
</Grid>
</Grid>
</Box>
</Grid>
</Grid>
</Box>
);
};
// const formatAMPM = (date) => {
// var hours = new Date(date).getHours();
// var minutes = new Date(date).getMinutes();
// var ampm = hours >= 12 ? "PM" : "AM";
// hours = hours % 12;
// hours = hours ? hours : 12;
// minutes = minutes < 10 ? "0" + minutes : minutes;
// var strTime = hours + ":" + minutes + " " + ampm;
// return strTime;
// };
export default RDViewOrder;

View File

@ -335,9 +335,13 @@ const ViewOrders = () => {
<TableBody> <TableBody>
{order?.orderItem.map((item, index) => { {order?.orderItem.map((item, index) => {
const subtotal = item.price * item.quantity; const subtotal = item.price * item.quantity;
const gstAmount = const gstAmount = (
((item.GST * item.price) / 100) * item.quantity; ((item.GST * item.price) / 100) *
const totalWithGST = subtotal + gstAmount; item.quantity
).toFixed(2);
const totalWithGST = (
subtotal + parseFloat(gstAmount)
).toFixed(2);
return ( return (
<TableRow key={index}> <TableRow key={index}>

View File

@ -270,9 +270,9 @@ const ViewInvoices = () => {
<TableBody> <TableBody>
{invoice?.orderId?.orderItem.map((item, index) => { {invoice?.orderId?.orderItem.map((item, index) => {
const subtotal = item.price * item.quantity; const subtotal = item.price * item.quantity;
const gstAmount = const gstAmount = (((item.GST * item.price) / 100) * item.quantity).toFixed(2);
((item.GST * item.price) / 100) * item.quantity; const totalWithGST = (subtotal + parseFloat(gstAmount)).toFixed(2);
const totalWithGST = subtotal + gstAmount;
return ( return (
<TableRow key={index}> <TableRow key={index}>