diff --git a/src/routes.js b/src/routes.js index ee064a3..072d38b 100644 --- a/src/routes.js +++ b/src/routes.js @@ -10,6 +10,10 @@ import ViewOrders from './views/pages/rdOrders/viewOrders' import PendingOrders from './views/pages/rdOrders/pendingOrders' import CancelledOrders from './views/pages/rdOrders/cancelledOrders' +import ProcessingInvoices from './views/pages/rdOrders/processingInvoices' +import ViewInvoices from './views/pages/rdOrders/invoiceView' +import DispatchedInvoices from './views/pages/rdOrders/dispatchedInvoices' +import DeliveredInvoices from './views/pages/rdOrders/deliveredInvoices' const Dashboard = React.lazy(() => import('./views/dashboard/Dashboard')) const Shop = React.lazy(() => import('./views/shops/Shop')) @@ -35,6 +39,10 @@ const routes = [ //RD Orders { path: '/new', name: 'New', element: NewOrders }, { path: '/pending', name: 'New', element: PendingOrders }, + { path: '/processing', name: 'New', element: ProcessingInvoices }, + { path: '/dispatched', name: 'New', element: DispatchedInvoices }, + { path: '/delivered', name: 'New', element: DeliveredInvoices }, + { path: '/invoice/:status/:id', name: 'New', element: ViewInvoices }, { path: '/cancelled', name: 'New', element: CancelledOrders }, { path: '/:status/:id', name: 'New', element: ViewOrders }, diff --git a/src/views/pages/rdOrders/deliveredInvoices.js b/src/views/pages/rdOrders/deliveredInvoices.js new file mode 100644 index 0000000..4e8b23b --- /dev/null +++ b/src/views/pages/rdOrders/deliveredInvoices.js @@ -0,0 +1,195 @@ +import React, { useState, useEffect, useRef } 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 debounce from lodash +import Axios from '../../../axios' + +const DeliveredInvoices = () => { + const [orders, setOrders] = useState([]) + const [loading, setLoading] = useState(true) + const [page, setPage] = useState(0) // 0-based page + const [rowsPerPage, setRowsPerPage] = useState(5) + const [totalOrders, setTotalOrders] = useState(0) + const [searchField, setSearchField] = useState('Order ID') + const [searchText, setSearchText] = useState('') + const navigate = useNavigate() + const token = isAutheticated() + const searchRef = useRef() + const fetchOrdersDebounced = useRef( + debounce((page, limit, searchField, searchText) => { + fetchOrders(page, limit, searchField, searchText) + }, 500), + ).current + + const fetchOrders = async (page, limit, searchField = '', searchText = '') => { + setLoading(true) + try { + const response = await Axios.get('/api/pd-get-delivered-invoices', { + headers: { + Authorization: `Bearer ${token}`, + }, + params: { + limit, + page: page + 1, + [searchField === 'Order ID' ? 'orderId' : 'invoiceId']: searchText || '', + }, + }) + console.log(response) + setOrders(response?.data?.invoices) + setTotalOrders(response?.data?.totalCount) + } catch (error) { + console.error('Error fetching orders:', error) + } finally { + setLoading(false) + } + } + + useEffect(() => { + fetchOrdersDebounced(page, rowsPerPage, searchField, searchText) + }, [page, rowsPerPage, searchField, searchText]) + + const handleSearchChange = (event) => { + const value = event.target.value + setSearchText(value) + searchRef.current = value + } + + const handleSearchFieldChange = (event) => { + setSearchField(event.target.value) + } + + const handleChangePage = (event, newPage) => { + setPage(newPage) + } + + const handleChangeRowsPerPage = (event) => { + setRowsPerPage(parseInt(event.target.value, 10)) + setPage(0) + } + + return ( + + + Delivered Invoice List + + + + Search By + + + + + + + + + Order ID + Invoice ID + Delivered Date + Items + Invoice Value + Status + Action + + + + {loading ? ( + Array.from(new Array(rowsPerPage)).map((_, index) => ( + + + + + + )) + ) : orders.length > 0 ? ( + orders.map((invoice) => ( + + {invoice.orderId.uniqueId} + {invoice.invoiceId} + + {new Date(invoice.courierstatus_timeline.delivered).toDateString()} + , {formatAMPM(invoice.courierstatus_timeline.delivered)} + + {invoice.items.length} + {invoice.invoiceAmount} + {invoice.courierStatus} + + + + + )) + ) : ( + + + No data found + + + )} + +
+ +
+
+ ) +} + +// Helper function to format time as AM/PM +const formatAMPM = (date) => { + const hours = new Date(date).getHours() + const minutes = new Date(date).getMinutes() + const ampm = hours >= 12 ? 'PM' : 'AM' + const formattedHours = hours % 12 || 12 + const formattedMinutes = minutes < 10 ? '0' + minutes : minutes + return `${formattedHours}:${formattedMinutes} ${ampm}` +} + +export default DeliveredInvoices diff --git a/src/views/pages/rdOrders/dispatchedInvoices.js b/src/views/pages/rdOrders/dispatchedInvoices.js new file mode 100644 index 0000000..23b19a7 --- /dev/null +++ b/src/views/pages/rdOrders/dispatchedInvoices.js @@ -0,0 +1,195 @@ +import React, { useState, useEffect, useRef } 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 debounce from lodash +import Axios from '../../../axios' + +const DispatchedInvoices = () => { + const [orders, setOrders] = useState([]) + const [loading, setLoading] = useState(true) + const [page, setPage] = useState(0) // 0-based page + const [rowsPerPage, setRowsPerPage] = useState(5) + const [totalOrders, setTotalOrders] = useState(0) + const [searchField, setSearchField] = useState('Order ID') + const [searchText, setSearchText] = useState('') + const navigate = useNavigate() + const token = isAutheticated() + const searchRef = useRef() + const fetchOrdersDebounced = useRef( + debounce((page, limit, searchField, searchText) => { + fetchOrders(page, limit, searchField, searchText) + }, 500), + ).current + + const fetchOrders = async (page, limit, searchField = '', searchText = '') => { + setLoading(true) + try { + const response = await Axios.get('/api/pd-get-dispatched-invoices', { + headers: { + Authorization: `Bearer ${token}`, + }, + params: { + limit, + page: page + 1, + [searchField === 'Order ID' ? 'orderId' : 'invoiceId']: searchText || '', + }, + }) + console.log(response) + setOrders(response?.data?.invoices) + setTotalOrders(response?.data?.totalCount) + } catch (error) { + console.error('Error fetching orders:', error) + } finally { + setLoading(false) + } + } + + useEffect(() => { + fetchOrdersDebounced(page, rowsPerPage, searchField, searchText) + }, [page, rowsPerPage, searchField, searchText]) + + const handleSearchChange = (event) => { + const value = event.target.value + setSearchText(value) + searchRef.current = value + } + + const handleSearchFieldChange = (event) => { + setSearchField(event.target.value) + } + + const handleChangePage = (event, newPage) => { + setPage(newPage) + } + + const handleChangeRowsPerPage = (event) => { + setRowsPerPage(parseInt(event.target.value, 10)) + setPage(0) + } + + return ( + + + Dispatched Invoice List + + + + Search By + + + + + + + + + Order ID + Invoice ID + Dispatched Date + Items + Invoice Value + Status + Action + + + + {loading ? ( + Array.from(new Array(rowsPerPage)).map((_, index) => ( + + + + + + )) + ) : orders.length > 0 ? ( + orders.map((invoice) => ( + + {invoice.orderId.uniqueId} + {invoice.invoiceId} + + {new Date(invoice.courierstatus_timeline.dispatched).toDateString()} + , {formatAMPM(invoice.courierstatus_timeline.dispatched)} + + {invoice.items.length} + {invoice.invoiceAmount} + {invoice.courierStatus} + + + + + )) + ) : ( + + + No data found + + + )} + +
+ +
+
+ ) +} + +// Helper function to format time as AM/PM +const formatAMPM = (date) => { + const hours = new Date(date).getHours() + const minutes = new Date(date).getMinutes() + const ampm = hours >= 12 ? 'PM' : 'AM' + const formattedHours = hours % 12 || 12 + const formattedMinutes = minutes < 10 ? '0' + minutes : minutes + return `${formattedHours}:${formattedMinutes} ${ampm}` +} + +export default DispatchedInvoices diff --git a/src/views/pages/rdOrders/viewInvoices.js b/src/views/pages/rdOrders/invoiceView.js similarity index 96% rename from src/views/pages/rdOrders/viewInvoices.js rename to src/views/pages/rdOrders/invoiceView.js index d6c5ac2..aa2df69 100644 --- a/src/views/pages/rdOrders/viewInvoices.js +++ b/src/views/pages/rdOrders/invoiceView.js @@ -20,15 +20,16 @@ import { Divider, Chip, } from '@mui/material' -import onvoicesData from '../../assets/incoicedata.json' + import { useNavigate, useParams } from 'react-router-dom' -import { TableContainer } from '@material-ui/core' +import { TableContainer } from '@mui/material' import axios from 'axios' // Import axios for HTTP requests import { isAutheticated } from 'src/auth' import Swal from 'sweetalert2' import OrderDetailsDialog from './partialOrderModal' import InvoiceTable from './invoiceTable' import PendingOrderTable from './pendingOrderTable' +import Axios from '../../../axios' const ViewInvoices = () => { const [invoice, setInvoice] = useState(null) // State to store order details @@ -53,7 +54,7 @@ const ViewInvoices = () => { useEffect(() => { const fetchOrderDetails = async () => { try { - const response = await axios.get(`/api/invoice/details/${id}`, { + const response = await Axios.get(`/api/pd-get-invoices/${id}`, { headers: { Authorization: `Bearer ${token}`, }, @@ -87,10 +88,11 @@ const ViewInvoices = () => { const handleConfirmUpdate = async (e) => { e.preventDefault() + try { if (invoiceStatus === 'dispatched') { - const res = await axios.put( - `/api/invoice/dispatched/${id}`, + const res = await Axios.put( + `/api/pd-invoice/dispatched/${id}`, { courierName, couriertrackingId, @@ -105,11 +107,11 @@ const ViewInvoices = () => { console.log(res) if (res.status === 200) { Swal.fire('Invoice Status updated', 'Invoice Dispatched', 'success') - navigate(`/orders/dispatched`) + navigate(`/dispatched`) } } else if (invoiceStatus === 'delivered') { - const deli = await axios.put( - `/api/invoice/delivered/${id}`, + const deli = await Axios.put( + `/api/pd-invoice/delivered/${id}`, {}, { @@ -123,7 +125,7 @@ const ViewInvoices = () => { if (deli.status === 200) { Swal.fire('Order Status updated', `Order Dispatched`, 'success') - navigate(`/orders/delivered`) + navigate(`/delivered`) } } } catch (error) { @@ -154,7 +156,7 @@ const ViewInvoices = () => { Invoice Id : {invoice?.invoiceId} - @@ -305,9 +307,7 @@ const ViewInvoices = () => { Customer Details - - SBU: {invoice?.orderId?.addedBy.SBU} - + Name: {invoice?.orderId?.addedBy.name} @@ -315,7 +315,7 @@ const ViewInvoices = () => { Email id: {invoice?.orderId?.addedBy.email} - Number: {invoice?.orderId?.addedBy.phone} + Number: {invoice?.orderId?.addedBy.mobile_number} diff --git a/src/views/pages/rdOrders/processingInvoices.js b/src/views/pages/rdOrders/processingInvoices.js new file mode 100644 index 0000000..247101a --- /dev/null +++ b/src/views/pages/rdOrders/processingInvoices.js @@ -0,0 +1,195 @@ +import React, { useState, useEffect, useRef } 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 debounce from lodash +import Axios from '../../../axios' + +const ProcessingInvoices = () => { + const [orders, setOrders] = useState([]) + const [loading, setLoading] = useState(true) + const [page, setPage] = useState(0) // 0-based page + const [rowsPerPage, setRowsPerPage] = useState(5) + const [totalOrders, setTotalOrders] = useState(0) + const [searchField, setSearchField] = useState('Order ID') + const [searchText, setSearchText] = useState('') + const navigate = useNavigate() + const token = isAutheticated() + const searchRef = useRef() + const fetchOrdersDebounced = useRef( + debounce((page, limit, searchField, searchText) => { + fetchOrders(page, limit, searchField, searchText) + }, 500), + ).current + + const fetchOrders = async (page, limit, searchField = '', searchText = '') => { + setLoading(true) + try { + const response = await Axios.get('/api/pd-get-processing-invoices', { + headers: { + Authorization: `Bearer ${token}`, + }, + params: { + limit, + page: page + 1, + [searchField === 'Order ID' ? 'orderId' : 'invoiceId']: searchText || '', + }, + }) + console.log(response) + setOrders(response?.data?.invoices) + setTotalOrders(response?.data?.totalCount) + } catch (error) { + console.error('Error fetching orders:', error) + } finally { + setLoading(false) + } + } + + useEffect(() => { + fetchOrdersDebounced(page, rowsPerPage, searchField, searchText) + }, [page, rowsPerPage, searchField, searchText]) + + const handleSearchChange = (event) => { + const value = event.target.value + setSearchText(value) + searchRef.current = value + } + + const handleSearchFieldChange = (event) => { + setSearchField(event.target.value) + } + + const handleChangePage = (event, newPage) => { + setPage(newPage) + } + + const handleChangeRowsPerPage = (event) => { + setRowsPerPage(parseInt(event.target.value, 10)) + setPage(0) + } + + return ( + + + Processing Invoice List + + + + Search By + + + + + + + + + Order ID + Invoice ID + Processing Date + Items + Invoice Value + Status + Action + + + + {loading ? ( + Array.from(new Array(rowsPerPage)).map((_, index) => ( + + + + + + )) + ) : orders.length > 0 ? ( + orders.map((invoice) => ( + + {invoice.orderId.uniqueId} + {invoice.invoiceId} + + {new Date(invoice.courierstatus_timeline.processing).toDateString()} + , {formatAMPM(invoice.courierstatus_timeline.processing)} + + {invoice.items.length} + {invoice.invoiceAmount} + {invoice.courierStatus} + + + + + )) + ) : ( + + + No data found + + + )} + +
+ +
+
+ ) +} + +// Helper function to format time as AM/PM +const formatAMPM = (date) => { + const hours = new Date(date).getHours() + const minutes = new Date(date).getMinutes() + const ampm = hours >= 12 ? 'PM' : 'AM' + const formattedHours = hours % 12 || 12 + const formattedMinutes = minutes < 10 ? '0' + minutes : minutes + return `${formattedHours}:${formattedMinutes} ${ampm}` +} + +export default ProcessingInvoices diff --git a/src/views/pages/rdOrders/viewOrders.js b/src/views/pages/rdOrders/viewOrders.js index 81d006f..7a83a74 100644 --- a/src/views/pages/rdOrders/viewOrders.js +++ b/src/views/pages/rdOrders/viewOrders.js @@ -126,6 +126,7 @@ const ViewOrders = () => { processquantity: item.remainingQuantity, // Add processquantity only for items with remainingQuantity > 0 })) console.log(processingOrderInvoice) + const cancellationRes = await Axios.post( `/api/pd-process-order`, { @@ -139,13 +140,18 @@ const ViewOrders = () => { }, }, ) + console.log(cancellationRes, 'this is the resp') if (cancellationRes.status === 200) { Swal.fire('Order Status updated', `Order in processing`, 'success') navigate(`/pending`) } } } catch (error) { - Swal.fire('Something went wrong ', error.message, 'error') + if (error.response.status === 400) { + Swal.fire('Stock not avaivalbe ', error.response.data.error, 'error') + } else { + Swal.fire('Something went wrong ', error.message, 'error') + } } // Perform update logic here setOpnePartialModal(false) @@ -208,12 +214,17 @@ const ViewOrders = () => { }, }, ) + if (cancellationRes.status === 200) { Swal.fire('Order Status updated', `Order in processing`, 'success') navigate(`/pending`) } } catch (error) { - Swal.fire('Something went wrong ', error.message, 'error') + if (error.response.status === 400) { + Swal.fire('Stock not avaivalbe ', error.response.data.error, 'error') + } else { + Swal.fire('Something went wrong ', error.message, 'error') + } } }