apis integration for the Partial order doen
Some checks failed
NPM Installation / build (17.x, windows-latest) (push) Has been cancelled
NPM Installation / build (16.x, ubuntu-latest) (push) Has been cancelled
NPM Installation / build (16.x, windows-latest) (push) Has been cancelled
NPM Installation / build (17.x, ubuntu-latest) (push) Has been cancelled
NPM Installation / build (18.x, ubuntu-latest) (push) Has been cancelled
NPM Installation / build (18.x, windows-latest) (push) Has been cancelled
Some checks failed
NPM Installation / build (17.x, windows-latest) (push) Has been cancelled
NPM Installation / build (16.x, ubuntu-latest) (push) Has been cancelled
NPM Installation / build (16.x, windows-latest) (push) Has been cancelled
NPM Installation / build (17.x, ubuntu-latest) (push) Has been cancelled
NPM Installation / build (18.x, ubuntu-latest) (push) Has been cancelled
NPM Installation / build (18.x, windows-latest) (push) Has been cancelled
This commit is contained in:
parent
91337d2b3f
commit
03dbed7d14
142
src/_nav.js
142
src/_nav.js
@ -63,110 +63,44 @@ const _nav = [
|
|||||||
to: '/kyc',
|
to: '/kyc',
|
||||||
icon: <CIcon icon={cilDescription} customClassName="nav-icon" />,
|
icon: <CIcon icon={cilDescription} customClassName="nav-icon" />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
// {
|
component: CNavGroup,
|
||||||
// component: CNavTitle,
|
name: 'RD Orders',
|
||||||
// name: 'Theme',
|
to: '/base',
|
||||||
// },
|
icon: <CIcon icon={cilPuzzle} customClassName="nav-icon" />,
|
||||||
// {
|
items: [
|
||||||
// component: CNavItem,
|
{
|
||||||
// name: 'Colors',
|
component: CNavItem,
|
||||||
// to: '/theme/colors',
|
name: 'New',
|
||||||
// icon: <CIcon icon={cilDrop} customClassName="nav-icon" />,
|
to: '/new',
|
||||||
// },
|
},
|
||||||
// {
|
{
|
||||||
// component: CNavItem,
|
component: CNavItem,
|
||||||
// name: 'Typography',
|
name: 'Pending',
|
||||||
// to: '/theme/typography',
|
to: '/pending',
|
||||||
// icon: <CIcon icon={cilPencil} customClassName="nav-icon" />,
|
},
|
||||||
// },
|
{
|
||||||
// {
|
component: CNavItem,
|
||||||
// component: CNavTitle,
|
name: 'Processing',
|
||||||
// name: 'Components',
|
to: '/processing',
|
||||||
// },
|
},
|
||||||
// {
|
{
|
||||||
// component: CNavGroup,
|
component: CNavItem,
|
||||||
// name: 'Base',
|
name: 'Dispathed',
|
||||||
// to: '/base',
|
to: '/dispatched',
|
||||||
// icon: <CIcon icon={cilPuzzle} customClassName="nav-icon" />,
|
},
|
||||||
// items: [
|
{
|
||||||
// {
|
component: CNavItem,
|
||||||
// component: CNavItem,
|
name: 'Delivered',
|
||||||
// name: 'Accordion',
|
to: '/delivered',
|
||||||
// to: '/base/accordion',
|
},
|
||||||
// },
|
{
|
||||||
// {
|
component: CNavItem,
|
||||||
// component: CNavItem,
|
name: 'Cancelled',
|
||||||
// name: 'Breadcrumb',
|
to: 'cancelled',
|
||||||
// to: '/base/breadcrumbs',
|
},
|
||||||
// },
|
],
|
||||||
// {
|
},
|
||||||
// component: CNavItem,
|
|
||||||
// name: 'Cards',
|
|
||||||
// to: '/base/cards',
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// component: CNavItem,
|
|
||||||
// name: 'Carousel',
|
|
||||||
// to: '/base/carousels',
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// component: CNavItem,
|
|
||||||
// name: 'Collapse',
|
|
||||||
// to: '/base/collapses',
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// component: CNavItem,
|
|
||||||
// name: 'List group',
|
|
||||||
// to: '/base/list-groups',
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// component: CNavItem,
|
|
||||||
// name: 'Navs & Tabs',
|
|
||||||
// to: '/base/navs',
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// component: CNavItem,
|
|
||||||
// name: 'Pagination',
|
|
||||||
// to: '/base/paginations',
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// component: CNavItem,
|
|
||||||
// name: 'Placeholders',
|
|
||||||
// to: '/base/placeholders',
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// component: CNavItem,
|
|
||||||
// name: 'Popovers',
|
|
||||||
// to: '/base/popovers',
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// component: CNavItem,
|
|
||||||
// name: 'Progress',
|
|
||||||
// to: '/base/progress',
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// component: CNavItem,
|
|
||||||
// name: 'Spinners',
|
|
||||||
// to: '/base/spinners',
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// component: CNavItem,
|
|
||||||
// name: 'Tables',
|
|
||||||
// to: '/base/tables',
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// component: CNavItem,
|
|
||||||
// name: 'Tabs',
|
|
||||||
// to: '/base/tabs',
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// component: CNavItem,
|
|
||||||
// name: 'Tooltips',
|
|
||||||
// to: '/base/tooltips',
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// {
|
// {
|
||||||
// component: CNavGroup,
|
// component: CNavGroup,
|
||||||
// name: 'Buttons',
|
// name: 'Buttons',
|
||||||
|
@ -5,6 +5,11 @@ import Cart from './views/pages/cart/cart'
|
|||||||
import OrderDetails from './views/orders/OrderDetails'
|
import OrderDetails from './views/orders/OrderDetails'
|
||||||
import ProductManual from './views/pages/productManual/productManual'
|
import ProductManual from './views/pages/productManual/productManual'
|
||||||
import ViewProductManual from './views/pages/productManual/viewProductManual'
|
import ViewProductManual from './views/pages/productManual/viewProductManual'
|
||||||
|
import NewOrders from './views/pages/rdOrders/newOrder'
|
||||||
|
import ViewOrders from './views/pages/rdOrders/viewOrders'
|
||||||
|
|
||||||
|
import PendingOrders from './views/pages/rdOrders/pendingOrders'
|
||||||
|
import CancelledOrders from './views/pages/rdOrders/cancelledOrders'
|
||||||
|
|
||||||
const Dashboard = React.lazy(() => import('./views/dashboard/Dashboard'))
|
const Dashboard = React.lazy(() => import('./views/dashboard/Dashboard'))
|
||||||
const Shop = React.lazy(() => import('./views/shops/Shop'))
|
const Shop = React.lazy(() => import('./views/shops/Shop'))
|
||||||
@ -27,6 +32,11 @@ const routes = [
|
|||||||
// Product manual
|
// Product manual
|
||||||
{ path: '/product-manual', name: 'Product Manual ', element: ProductManual },
|
{ path: '/product-manual', name: 'Product Manual ', element: ProductManual },
|
||||||
{ path: '/product-manual/:id', name: 'Product Manual ', element: ViewProductManual },
|
{ path: '/product-manual/:id', name: 'Product Manual ', element: ViewProductManual },
|
||||||
|
//RD Orders
|
||||||
|
{ path: '/new', name: 'New', element: NewOrders },
|
||||||
|
{ path: '/pending', name: 'New', element: PendingOrders },
|
||||||
|
{ path: '/cancelled', name: 'New', element: CancelledOrders },
|
||||||
|
{ path: '/:status/:id', name: 'New', element: ViewOrders },
|
||||||
|
|
||||||
{ path: '/my-profile', name: 'Profile', element: MyProfile },
|
{ path: '/my-profile', name: 'Profile', element: MyProfile },
|
||||||
{ path: '/change-password', name: 'Change password', element: ChangePassword },
|
{ path: '/change-password', name: 'Change password', element: ChangePassword },
|
||||||
|
@ -57,6 +57,7 @@ const Order = () => {
|
|||||||
limit: rowsPerPage, // number of rows per page
|
limit: rowsPerPage, // number of rows per page
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
console.log('total orders ', response)
|
||||||
setOrders(response.data.plcaedOrders)
|
setOrders(response.data.plcaedOrders)
|
||||||
setTotalOrders(response.data.totalOrders) // Ensure the API returns the total count of orders
|
setTotalOrders(response.data.totalOrders) // Ensure the API returns the total count of orders
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -193,37 +193,6 @@ const OrderDetails = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Status History Table */}
|
|
||||||
{statusHistory.length > 0 && (
|
|
||||||
<Box mt={8}>
|
|
||||||
<Typography variant="h5" sx={{ mb: '1rem' }}>
|
|
||||||
Status History
|
|
||||||
</Typography>
|
|
||||||
<TableContainer
|
|
||||||
component={Paper}
|
|
||||||
elevation={0}
|
|
||||||
sx={{ borderBottom: '1.5px solid #CFCFD5', borderRadius: '0.8rem' }}
|
|
||||||
>
|
|
||||||
<Table sx={{ minWidth: 650 }} size="large">
|
|
||||||
<TableHead>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell>Status</TableCell>
|
|
||||||
<TableCell>Timestamp</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>
|
|
||||||
{statusHistory.map((status, index) => (
|
|
||||||
<TableRow key={index}>
|
|
||||||
<TableCell>{status.status}</TableCell>
|
|
||||||
<TableCell>{new Date(status.timestamp).toLocaleString()}</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</TableContainer>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,7 @@ const Login = () => {
|
|||||||
console.log(res)
|
console.log(res)
|
||||||
if (res.data.success === true && res.data.user.role === 'principal-Distributor') {
|
if (res.data.success === true && res.data.user.role === 'principal-Distributor') {
|
||||||
localStorage.setItem('authToken', res.data.token)
|
localStorage.setItem('authToken', res.data.token)
|
||||||
|
console.log(res.data.token)
|
||||||
dispatch(clearCart())
|
dispatch(clearCart())
|
||||||
navigate('/dashboard')
|
navigate('/dashboard')
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
204
src/views/pages/rdOrders/cancelledOrders.js
Normal file
204
src/views/pages/rdOrders/cancelledOrders.js
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
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 { isAutheticated } from 'src/auth'
|
||||||
|
import Axios from '../../../axios'
|
||||||
|
|
||||||
|
const CancelledOrder = () => {
|
||||||
|
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('uniqueId') // Default search field
|
||||||
|
const [searchText, setSearchText] = useState('') // Default search text is empty
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const token = isAutheticated()
|
||||||
|
|
||||||
|
// Fetch orders based on page, limit, and search criteria
|
||||||
|
const fetchOrders = async (page, limit, searchField, searchText) => {
|
||||||
|
setLoading(true)
|
||||||
|
try {
|
||||||
|
const response = await Axios.get('/api/pd-get-cancelled-orders', {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
page: page + 1, // Pages are 1-indexed in backend
|
||||||
|
limit,
|
||||||
|
searchField: searchText ? searchField : undefined, // Only pass searchField if there's a searchText
|
||||||
|
searchText: searchText || undefined, // Only pass searchText if it's not empty
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if (response?.status === 200) {
|
||||||
|
setOrders(response?.data?.plcaedOrders)
|
||||||
|
setTotalOrders(response?.data?.totalOrders)
|
||||||
|
} else {
|
||||||
|
setOrders([])
|
||||||
|
setTotalOrders(0)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching orders:', error)
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch all orders initially and when page/rowsPerPage changes
|
||||||
|
useEffect(() => {
|
||||||
|
fetchOrders(page, rowsPerPage, searchField, searchText)
|
||||||
|
}, [page, rowsPerPage])
|
||||||
|
|
||||||
|
// Trigger search when search text or search field changes
|
||||||
|
const handleSearchChange = (event) => {
|
||||||
|
setSearchText(event.target.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (searchText.trim()) {
|
||||||
|
// Trigger search only when there is search text
|
||||||
|
fetchOrders(0, rowsPerPage, searchField, searchText)
|
||||||
|
} else {
|
||||||
|
// If searchText is cleared, fetch all orders again
|
||||||
|
fetchOrders(page, rowsPerPage, searchField, '')
|
||||||
|
}
|
||||||
|
}, [searchText, searchField])
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<Box>
|
||||||
|
<Typography variant="h4" mb={2} textAlign="center">
|
||||||
|
New Order Placed 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="uniqueId">Order ID</MenuItem>
|
||||||
|
<MenuItem value="status">Status</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>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={6}>
|
||||||
|
<Skeleton height={40} />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : orders?.length > 0 ? (
|
||||||
|
orders.map((order) => (
|
||||||
|
<TableRow key={order._id}>
|
||||||
|
<TableCell>{order.uniqueId}</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(`/${order.status}/${order._id}`)}
|
||||||
|
>
|
||||||
|
View
|
||||||
|
</Button>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={6} 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
|
||||||
|
hours = hours ? hours : 12
|
||||||
|
minutes = minutes < 10 ? '0' + minutes : minutes
|
||||||
|
var strTime = hours + ':' + minutes + ' ' + ampm
|
||||||
|
return strTime
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CancelledOrder
|
73
src/views/pages/rdOrders/invoiceTable.js
Normal file
73
src/views/pages/rdOrders/invoiceTable.js
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import React, { useState, useEffect } from 'react'
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableContainer,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
Paper,
|
||||||
|
Button,
|
||||||
|
Chip,
|
||||||
|
} from '@mui/material'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
const InvoiceTable = ({ invoices }) => {
|
||||||
|
return (
|
||||||
|
<TableContainer component={Paper}>
|
||||||
|
<Table>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>Invoice ID</TableCell>
|
||||||
|
|
||||||
|
<TableCell>Items</TableCell>
|
||||||
|
<TableCell>Subtotal</TableCell>
|
||||||
|
<TableCell>GST Total</TableCell>
|
||||||
|
<TableCell>Invoice Amount</TableCell>
|
||||||
|
<TableCell>Courier Status</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{false ? (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={8} align="center">
|
||||||
|
Loading...
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
) : (
|
||||||
|
invoices.map((invoice) => (
|
||||||
|
<TableRow key={invoice.invoiceId}>
|
||||||
|
<TableCell>{invoice.invoiceId}</TableCell>
|
||||||
|
|
||||||
|
<TableCell>
|
||||||
|
{invoice.items.map((item) => (
|
||||||
|
<div key={item.productId}>
|
||||||
|
{item.name} ({item.SKU}) x <b>{item.processquantity}</b>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>{invoice.subtotal}</TableCell>
|
||||||
|
<TableCell>{invoice.gstTotal}</TableCell>
|
||||||
|
<TableCell>{invoice.invoiceAmount}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Chip
|
||||||
|
label={invoice.courierStatus}
|
||||||
|
color={
|
||||||
|
invoice.courierStatus === 'delivered'
|
||||||
|
? 'success'
|
||||||
|
: invoice.courierStatus === 'dispatched'
|
||||||
|
? 'primary'
|
||||||
|
: 'warning'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default InvoiceTable
|
204
src/views/pages/rdOrders/newOrder.js
Normal file
204
src/views/pages/rdOrders/newOrder.js
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
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 { isAutheticated } from 'src/auth'
|
||||||
|
import Axios from '../../../axios'
|
||||||
|
|
||||||
|
const NewOrders = () => {
|
||||||
|
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('uniqueId') // Default search field
|
||||||
|
const [searchText, setSearchText] = useState('') // Default search text is empty
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const token = isAutheticated()
|
||||||
|
|
||||||
|
// Fetch orders based on page, limit, and search criteria
|
||||||
|
const fetchOrders = async (page, limit, searchField, searchText) => {
|
||||||
|
setLoading(true)
|
||||||
|
try {
|
||||||
|
const response = await Axios.get('/api/pd-get-new-orders', {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
page: page + 1, // Pages are 1-indexed in backend
|
||||||
|
limit,
|
||||||
|
searchField: searchText ? searchField : undefined, // Only pass searchField if there's a searchText
|
||||||
|
searchText: searchText || undefined, // Only pass searchText if it's not empty
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if (response?.status === 200) {
|
||||||
|
setOrders(response?.data?.plcaedOrders)
|
||||||
|
setTotalOrders(response?.data?.totalOrders)
|
||||||
|
} else {
|
||||||
|
setOrders([])
|
||||||
|
setTotalOrders(0)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching orders:', error)
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch all orders initially and when page/rowsPerPage changes
|
||||||
|
useEffect(() => {
|
||||||
|
fetchOrders(page, rowsPerPage, searchField, searchText)
|
||||||
|
}, [page, rowsPerPage])
|
||||||
|
|
||||||
|
// Trigger search when search text or search field changes
|
||||||
|
const handleSearchChange = (event) => {
|
||||||
|
setSearchText(event.target.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (searchText.trim()) {
|
||||||
|
// Trigger search only when there is search text
|
||||||
|
fetchOrders(0, rowsPerPage, searchField, searchText)
|
||||||
|
} else {
|
||||||
|
// If searchText is cleared, fetch all orders again
|
||||||
|
fetchOrders(page, rowsPerPage, searchField, '')
|
||||||
|
}
|
||||||
|
}, [searchText, searchField])
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<Box>
|
||||||
|
<Typography variant="h4" mb={2} textAlign="center">
|
||||||
|
New Order Placed 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="uniqueId">Order ID</MenuItem>
|
||||||
|
<MenuItem value="status">Status</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>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={6}>
|
||||||
|
<Skeleton height={40} />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : orders?.length > 0 ? (
|
||||||
|
orders.map((order) => (
|
||||||
|
<TableRow key={order._id}>
|
||||||
|
<TableCell>{order.uniqueId}</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(`/${order.status}/${order._id}`)}
|
||||||
|
>
|
||||||
|
View
|
||||||
|
</Button>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={6} 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
|
||||||
|
hours = hours ? hours : 12
|
||||||
|
minutes = minutes < 10 ? '0' + minutes : minutes
|
||||||
|
var strTime = hours + ':' + minutes + ' ' + ampm
|
||||||
|
return strTime
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewOrders
|
120
src/views/pages/rdOrders/partialOrderModal.js
Normal file
120
src/views/pages/rdOrders/partialOrderModal.js
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
import React, { useState } from 'react'
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogTitle,
|
||||||
|
Button,
|
||||||
|
TextField,
|
||||||
|
Typography,
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableContainer,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
Paper,
|
||||||
|
Grid,
|
||||||
|
} from '@mui/material'
|
||||||
|
|
||||||
|
const OrderDetailsDialog = ({ open, onClose, order, onSubmit }) => {
|
||||||
|
// Create a state to store availability input for each product
|
||||||
|
console.log(order)
|
||||||
|
const [availability, setAvailability] = useState(
|
||||||
|
order?.orderItem.map((item) => ({
|
||||||
|
...item, // Keep all original properties from orderItem
|
||||||
|
processquantity: item.remainingQuantity, // Add availability field with default value equal to quantity
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Handle input change for availability
|
||||||
|
const handleAvailabilityChange = (index, value) => {
|
||||||
|
const updatedAvailability = [...availability]
|
||||||
|
const newValue = Math.max(0, Math.min(value, updatedAvailability[index].remainingQuantity)) // Ensure value is between 0 and available quantity
|
||||||
|
updatedAvailability[index].processquantity = newValue
|
||||||
|
setAvailability(updatedAvailability)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle form submission
|
||||||
|
const handleSubmit = () => {
|
||||||
|
onSubmit(availability) // Pass updated availability to parent component
|
||||||
|
onClose() // Close modal
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onClose={onClose} maxWidth="md" fullWidth>
|
||||||
|
<DialogTitle>Modify Product Availability</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<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">Quantity</TableCell>
|
||||||
|
<TableCell align="right">Availability</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.remainingQuantity
|
||||||
|
const gstAmount = ((item.GST * item.price) / 100) * item.remainingQuantity
|
||||||
|
const totalWithGST = subtotal + gstAmount
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow key={index}>
|
||||||
|
<TableCell>
|
||||||
|
<img
|
||||||
|
src={item.productId.image}
|
||||||
|
alt={item.productId.name}
|
||||||
|
style={{ width: 50, height: 50, marginRight: 10 }}
|
||||||
|
/>
|
||||||
|
<Typography variant="subtitle1">{item.productId.name}</Typography>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="right">₹{item.price}</TableCell>
|
||||||
|
<TableCell align="right">{item.remainingQuantity}</TableCell>
|
||||||
|
<TableCell align="right">
|
||||||
|
<TextField
|
||||||
|
sx={{ minWidth: '100px' }}
|
||||||
|
type="number"
|
||||||
|
value={availability[index].processquantity}
|
||||||
|
onChange={(e) =>
|
||||||
|
handleAvailabilityChange(index, Number(e.target.value))
|
||||||
|
}
|
||||||
|
inputProps={{
|
||||||
|
min: 0,
|
||||||
|
max: item.remainingQuantity,
|
||||||
|
}}
|
||||||
|
style={{ width: '60px', textAlign: 'center' }}
|
||||||
|
/>
|
||||||
|
</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>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={onClose}>Cancel</Button>
|
||||||
|
<Button onClick={handleSubmit} variant="contained" color="primary">
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OrderDetailsDialog
|
76
src/views/pages/rdOrders/pendingOrderTable.js
Normal file
76
src/views/pages/rdOrders/pendingOrderTable.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Grid,
|
||||||
|
TableContainer,
|
||||||
|
Paper,
|
||||||
|
Table,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
TableCell,
|
||||||
|
TableBody,
|
||||||
|
Typography,
|
||||||
|
} from '@mui/material'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const PendingOrderTable = ({ order }) => {
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<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">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) => {
|
||||||
|
// Check if remainingQuantity is greater than 0
|
||||||
|
if (item.remainingQuantity > 0) {
|
||||||
|
const subtotal = item.price * item.remainingQuantity
|
||||||
|
const gstAmount = ((item.GST * item.price) / 100) * item.remainingQuantity
|
||||||
|
const totalWithGST = subtotal + gstAmount
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow key={index}>
|
||||||
|
<TableCell>
|
||||||
|
<img
|
||||||
|
src={item.productId.image}
|
||||||
|
alt={item.productId.name}
|
||||||
|
style={{
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
marginRight: 10,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Typography variant="subtitle1">{item.productId.name}</Typography>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="right">₹{item.price}</TableCell>
|
||||||
|
<TableCell align="right">{item.remainingQuantity}</TableCell>
|
||||||
|
<TableCell align="right">₹{subtotal}</TableCell>
|
||||||
|
<TableCell align="right">{item.GST}%</TableCell>
|
||||||
|
<TableCell align="right">₹{gstAmount}</TableCell>
|
||||||
|
<TableCell align="right">₹{totalWithGST}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// Return null if remainingQuantity is 0
|
||||||
|
return null
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PendingOrderTable
|
188
src/views/pages/rdOrders/pendingOrders.js
Normal file
188
src/views/pages/rdOrders/pendingOrders.js
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
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 { isAutheticated } from 'src/auth'
|
||||||
|
import Axios from '../../../axios'
|
||||||
|
|
||||||
|
const PendingOrders = () => {
|
||||||
|
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('Order ID')
|
||||||
|
const [searchText, setSearchText] = useState('')
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const token = isAutheticated()
|
||||||
|
|
||||||
|
// Fetch orders with pagination
|
||||||
|
const fetchOrders = async (page, limit) => {
|
||||||
|
setLoading(true)
|
||||||
|
try {
|
||||||
|
const response = await Axios.get('/api/pd-get-pending-orders', {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
page: page + 1, // Adjusting for zero-based index in the UI
|
||||||
|
limit,
|
||||||
|
searchField,
|
||||||
|
searchText,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
console.log(response)
|
||||||
|
setOrders(response?.data?.plcaedOrders)
|
||||||
|
setTotalOrders(response?.data?.totalOrders)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching orders:', error)
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchOrders(page, rowsPerPage)
|
||||||
|
}, [page, rowsPerPage, searchField, searchText])
|
||||||
|
|
||||||
|
const handleSearchChange = (event) => {
|
||||||
|
setSearchText(event.target.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 (
|
||||||
|
<Box>
|
||||||
|
<Typography variant="h4" mb={2} textAlign="center">
|
||||||
|
Pending 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>
|
||||||
|
</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>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={6}>
|
||||||
|
<Skeleton height={40} />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : orders?.length > 0 ? (
|
||||||
|
orders?.map((order) => (
|
||||||
|
<TableRow key={order._id}>
|
||||||
|
<TableCell>{order.uniqueId}</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(`/${order.status}/${order._id}`)}
|
||||||
|
>
|
||||||
|
View
|
||||||
|
</Button>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={6} 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
|
||||||
|
hours = hours ? hours : 12
|
||||||
|
minutes = minutes < 10 ? '0' + minutes : minutes
|
||||||
|
var strTime = hours + ':' + minutes + ' ' + ampm
|
||||||
|
return strTime
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PendingOrders
|
481
src/views/pages/rdOrders/viewInvoices.js
Normal file
481
src/views/pages/rdOrders/viewInvoices.js
Normal file
@ -0,0 +1,481 @@
|
|||||||
|
import React, { useState, useEffect } from 'react'
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Typography,
|
||||||
|
Grid,
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
Paper,
|
||||||
|
DialogContentText,
|
||||||
|
DialogTitle,
|
||||||
|
TextField,
|
||||||
|
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 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'
|
||||||
|
|
||||||
|
const ViewInvoices = () => {
|
||||||
|
const [invoice, setInvoice] = useState(null) // State to store order details
|
||||||
|
const [status, setStatus] = useState('')
|
||||||
|
const [openConfirmDialog, setOpenConfirmDialog] = useState(false)
|
||||||
|
const [openDispatchDialog, setOpenDispatchDialog] = useState(false)
|
||||||
|
|
||||||
|
const [openDeliveredDialog, setOpenDeliveredDialog] = useState(false) // New dialog state for delivery confirmation
|
||||||
|
const [courierName, setCourierName] = useState('')
|
||||||
|
const [couriertrackingId, setCourierId] = useState('')
|
||||||
|
|
||||||
|
const [deliveryDate, setDeliveryDate] = useState('')
|
||||||
|
const token = isAutheticated() // State for delivery date
|
||||||
|
const [invoiceStatus, setInvoiceStatus] = useState('')
|
||||||
|
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/invoice/details/${id}`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
console.log(response)
|
||||||
|
setInvoice(response.data)
|
||||||
|
setStatus(response.data.courierStatus)
|
||||||
|
|
||||||
|
setLoading(false)
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
setError('Failed to fetch order details')
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchOrderDetails()
|
||||||
|
}, [id])
|
||||||
|
|
||||||
|
const handleStatusChange = (event) => {
|
||||||
|
setInvoiceStatus(event.target.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleUpdateClick = () => {
|
||||||
|
if (invoiceStatus === 'dispatched') {
|
||||||
|
setOpenDispatchDialog(true)
|
||||||
|
} else if (invoiceStatus === 'delivered') {
|
||||||
|
setOpenDeliveredDialog(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleConfirmUpdate = async (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
try {
|
||||||
|
if (invoiceStatus === 'dispatched') {
|
||||||
|
const res = await axios.put(
|
||||||
|
`/api/invoice/dispatched/${id}`,
|
||||||
|
{
|
||||||
|
courierName,
|
||||||
|
couriertrackingId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
console.log(res)
|
||||||
|
if (res.status === 200) {
|
||||||
|
Swal.fire('Invoice Status updated', 'Invoice Dispatched', 'success')
|
||||||
|
navigate(`/orders/dispatched`)
|
||||||
|
}
|
||||||
|
} else if (invoiceStatus === 'delivered') {
|
||||||
|
const deli = await axios.put(
|
||||||
|
`/api/invoice/delivered/${id}`,
|
||||||
|
{},
|
||||||
|
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if (deli.status === 200) {
|
||||||
|
Swal.fire('Order Status updated', `Order Dispatched`, 'success')
|
||||||
|
|
||||||
|
navigate(`/orders/delivered`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
Swal.fire('Something went wrong ', error.message, 'error')
|
||||||
|
}
|
||||||
|
|
||||||
|
setOpenDispatchDialog(false)
|
||||||
|
|
||||||
|
setOpenDeliveredDialog(false) // Close delivered dialog
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCancel = async () => {
|
||||||
|
setOpenDispatchDialog(false)
|
||||||
|
setOpenDeliveredDialog(false) // Close delivered dialog
|
||||||
|
}
|
||||||
|
|
||||||
|
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' }}>
|
||||||
|
Invoice Id : {invoice?.invoiceId}
|
||||||
|
</Typography>
|
||||||
|
<Button color="primary" onClick={() => navigate(`/orders/${status}`)} variant="contained">
|
||||||
|
Back
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item md={8} xl={8} lg={8}>
|
||||||
|
<Box sx={{ padding: 2, background: '#fff' }}>
|
||||||
|
<Typography variant="h4" gutterBottom>
|
||||||
|
Invoice
|
||||||
|
</Typography>
|
||||||
|
{/* <InvoiceTable invoices={invoice} /> */}
|
||||||
|
<TableContainer component={Paper}>
|
||||||
|
<Table>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>Invoice ID</TableCell>
|
||||||
|
|
||||||
|
<TableCell>Items</TableCell>
|
||||||
|
<TableCell>Subtotal</TableCell>
|
||||||
|
<TableCell>GST Total</TableCell>
|
||||||
|
<TableCell>Invoice Amount</TableCell>
|
||||||
|
<TableCell>Courier Status</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
<TableRow key={invoice.invoiceId}>
|
||||||
|
<TableCell>{invoice.invoiceId}</TableCell>
|
||||||
|
|
||||||
|
<TableCell>
|
||||||
|
{invoice.items.map((item) => (
|
||||||
|
<div key={item.productId}>
|
||||||
|
{item.name} ({item.SKU}) x <b>{item.processquantity}</b>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>{invoice.subtotal}</TableCell>
|
||||||
|
<TableCell>{invoice.gstTotal}</TableCell>
|
||||||
|
<TableCell>{invoice.invoiceAmount}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Chip
|
||||||
|
label={invoice.courierStatus}
|
||||||
|
color={
|
||||||
|
invoice.courierStatus === 'delivered'
|
||||||
|
? 'success'
|
||||||
|
: invoice.courierStatus === 'dispatched'
|
||||||
|
? 'primary'
|
||||||
|
: 'warning'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
|
||||||
|
{/* <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">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>
|
||||||
|
{invoice?.orderId?.orderItem.map((item, index) => {
|
||||||
|
const subtotal = item.price * item.quantity;
|
||||||
|
const gstAmount =
|
||||||
|
((item.GST * item.price) / 100) * item.quantity;
|
||||||
|
const totalWithGST = subtotal + gstAmount;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow key={index}>
|
||||||
|
<TableCell>
|
||||||
|
<img
|
||||||
|
src={item.productId.image}
|
||||||
|
alt={item.productId.name}
|
||||||
|
style={{
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
marginRight: 10,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Typography variant="subtitle1">
|
||||||
|
{item.productId.name}
|
||||||
|
</Typography>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="right">₹{item.price}</TableCell>
|
||||||
|
<TableCell align="right">{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> */}
|
||||||
|
|
||||||
|
<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>
|
||||||
|
Invoice Summary
|
||||||
|
</Typography>
|
||||||
|
<Divider sx={{ marginBottom: 2 }} />
|
||||||
|
<Typography>Total Items: {invoice?.items.length}</Typography>
|
||||||
|
|
||||||
|
<Typography>Total Subtotal: ₹{invoice?.subtotal}</Typography>
|
||||||
|
<Typography>Total GST: ₹{invoice?.gstTotal}</Typography>
|
||||||
|
<Typography variant="h5" sx={{ marginTop: 2 }}>
|
||||||
|
Grand Total: ₹{invoice?.invoiceAmount}
|
||||||
|
</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' }}>
|
||||||
|
Customer Details
|
||||||
|
</Typography>
|
||||||
|
<Typography sx={{ mb: '0.5rem' }}>
|
||||||
|
<strong>SBU:</strong> {invoice?.orderId?.addedBy.SBU}
|
||||||
|
</Typography>
|
||||||
|
<Typography sx={{ mb: '0.5rem' }}>
|
||||||
|
<strong>Name:</strong> {invoice?.orderId?.addedBy.name}
|
||||||
|
</Typography>
|
||||||
|
<Typography sx={{ mb: '0.5rem' }}>
|
||||||
|
<strong>Email id:</strong> {invoice?.orderId?.addedBy.email}
|
||||||
|
</Typography>
|
||||||
|
<Typography sx={{ mb: '0.5rem' }}>
|
||||||
|
<strong>Number:</strong> {invoice?.orderId?.addedBy.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' }}>{invoice?.orderId?.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' }}>{invoice?.orderId?.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' }}>{invoice?.orderId?.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>
|
||||||
|
{invoice?.courierStatus === "cancelled" && (
|
||||||
|
<Typography sx={{ mb: "0.5rem", color: "red" }}>
|
||||||
|
{order?.order_Cancelled_Reason}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Grid> */}
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
{invoice?.status !== 'delivered' && (
|
||||||
|
<FormControl fullWidth sx={{ mt: 2 }}>
|
||||||
|
<select className="form-control" onChange={handleStatusChange} value={invoiceStatus}>
|
||||||
|
{status === 'processing' && (
|
||||||
|
<>
|
||||||
|
<option value="">Processing</option>
|
||||||
|
<option value="dispatched">Dispatch</option>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{status === 'dispatched' && (
|
||||||
|
<>
|
||||||
|
<option value="">Dispatched</option>
|
||||||
|
<option value="delivered">Delivered</option>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{invoiceStatus && (
|
||||||
|
<Button variant="contained" color="primary" onClick={handleUpdateClick} sx={{ mt: 2 }}>
|
||||||
|
Update Status
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* Dialogs for updating status */}
|
||||||
|
<Dialog open={openConfirmDialog} onClose={handleCancel}>
|
||||||
|
<DialogTitle>Update Order Status</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText>
|
||||||
|
Are you sure you want to update the status to {invoiceStatus}?
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handleCancel} variant="outlined" color="primary">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleConfirmUpdate} variant="contained" color="success" autoFocus>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
{/* Dialog for dispatch details */}
|
||||||
|
<Dialog open={openDispatchDialog} onClose={handleCancel}>
|
||||||
|
<DialogTitle>Dispatch Details</DialogTitle>
|
||||||
|
<form onSubmit={handleConfirmUpdate}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText>Please provide courier name and ID for dispatch:</DialogContentText>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
required
|
||||||
|
margin="dense"
|
||||||
|
label="Courier Name"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={courierName}
|
||||||
|
onChange={(e) => setCourierName(e.target.value)}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
margin="dense"
|
||||||
|
label="Courier ID"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={couriertrackingId}
|
||||||
|
onChange={(e) => setCourierId(e.target.value)}
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handleCancel} color="primary">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button type="submit" variant="contained" color="success" autoFocus>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</form>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
<Dialog open={openDeliveredDialog} onClose={handleCancel}>
|
||||||
|
<DialogTitle>Confirm Delivery</DialogTitle>
|
||||||
|
<form onSubmit={handleConfirmUpdate}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText>Please confirm the delivery details:</DialogContentText>
|
||||||
|
<FormControl required>
|
||||||
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
required
|
||||||
|
margin="dense"
|
||||||
|
label="Delivery Date"
|
||||||
|
type="date"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={deliveryDate}
|
||||||
|
onChange={(e) => setDeliveryDate(e.target.value)}
|
||||||
|
InputLabelProps={{
|
||||||
|
shrink: true,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handleCancel} variant="outlined" color="primary">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleConfirmUpdate} variant="contained" color="success" autoFocus>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</form>
|
||||||
|
</Dialog>
|
||||||
|
</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 ViewInvoices
|
634
src/views/pages/rdOrders/viewOrders.js
Normal file
634
src/views/pages/rdOrders/viewOrders.js
Normal file
@ -0,0 +1,634 @@
|
|||||||
|
import React, { useState, useEffect } from 'react'
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Typography,
|
||||||
|
Grid,
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
Paper,
|
||||||
|
DialogContentText,
|
||||||
|
DialogTitle,
|
||||||
|
TextField,
|
||||||
|
Divider,
|
||||||
|
} from '@mui/material'
|
||||||
|
|
||||||
|
import { useNavigate, useParams } from 'react-router-dom'
|
||||||
|
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 ViewOrders = () => {
|
||||||
|
const [order, setOrder] = useState(null) // State to store order details
|
||||||
|
const [status, setStatus] = useState('')
|
||||||
|
const [openConfirmDialog, setOpenConfirmDialog] = useState(false)
|
||||||
|
const [openDispatchDialog, setOpenDispatchDialog] = useState(false)
|
||||||
|
const [openCancelDialog, setOpenCancelDialog] = useState(false)
|
||||||
|
const [openDeliveredDialog, setOpenDeliveredDialog] = useState(false) // New dialog state for delivery confirmation
|
||||||
|
const [courierName, setCourierName] = useState('')
|
||||||
|
const [courierId, setCourierId] = useState('')
|
||||||
|
const [cancellationReason, setCancellationReason] = useState('')
|
||||||
|
const [deliveryDate, setDeliveryDate] = useState('')
|
||||||
|
const token = isAutheticated() // State for delivery date
|
||||||
|
const [orderStatus, setOrderStatus] = useState('')
|
||||||
|
const [loading, setLoading] = useState(true) // Loading state
|
||||||
|
const [error, setError] = useState(null) // Error state
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const { id } = useParams()
|
||||||
|
const [parialModal, setOpnePartialModal] = useState(false)
|
||||||
|
// Get order ID from URL params
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchOrderDetails = async () => {
|
||||||
|
try {
|
||||||
|
const response = await Axios.get(`/api/pd-get-single-place-order/${id}`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
console.log(response)
|
||||||
|
setOrder(response.data.singleOrder)
|
||||||
|
setStatus(response.data.singleOrder?.status)
|
||||||
|
|
||||||
|
setLoading(false)
|
||||||
|
} catch (err) {
|
||||||
|
setError('Failed to fetch order details')
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchOrderDetails()
|
||||||
|
}, [id])
|
||||||
|
|
||||||
|
const handleStatusChange = (event) => {
|
||||||
|
setOrderStatus(event.target.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleUpdateClick = () => {
|
||||||
|
if (orderStatus === 'dispatched') {
|
||||||
|
setOpenDispatchDialog(true)
|
||||||
|
} else if (orderStatus === 'partial-processing') {
|
||||||
|
setOpnePartialModal(true)
|
||||||
|
} else if (orderStatus === 'cancelled') {
|
||||||
|
setOpenCancelDialog(true)
|
||||||
|
} else if (orderStatus === 'delivered') {
|
||||||
|
setOpenDeliveredDialog(true)
|
||||||
|
} else {
|
||||||
|
setOpenConfirmDialog(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleConfirmUpdate = async (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
try {
|
||||||
|
if (orderStatus === 'cancelled') {
|
||||||
|
if (!cancellationReason) {
|
||||||
|
Swal.fire('Please give the order cancellation reason')
|
||||||
|
}
|
||||||
|
const cancellationRes = await Axios.put(
|
||||||
|
`/api/pd-cancel-order/${id}`,
|
||||||
|
{
|
||||||
|
cancellationReason: cancellationReason,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if (cancellationRes.status === 200) {
|
||||||
|
Swal.fire(
|
||||||
|
'Order Status updated',
|
||||||
|
`Order got cancelled due to${cancellationReason}`,
|
||||||
|
'success',
|
||||||
|
)
|
||||||
|
navigate(`/cancelled`)
|
||||||
|
}
|
||||||
|
} else if (orderStatus === 'processing') {
|
||||||
|
const processingOrderInvoice = order?.orderItem
|
||||||
|
.filter((item) => item.remainingQuantity > 0) // Only include items with remainingQuantity > 0
|
||||||
|
.map((item) => ({
|
||||||
|
...item,
|
||||||
|
productId: item.productId,
|
||||||
|
processquantity: item.remainingQuantity, // Add processquantity only for items with remainingQuantity > 0
|
||||||
|
}))
|
||||||
|
console.log(processingOrderInvoice)
|
||||||
|
const cancellationRes = await Axios.post(
|
||||||
|
`/api/pd-process-order`,
|
||||||
|
{
|
||||||
|
invoiceItems: processingOrderInvoice,
|
||||||
|
orderId: order._id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
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')
|
||||||
|
}
|
||||||
|
// Perform update logic here
|
||||||
|
setOpnePartialModal(false)
|
||||||
|
setOpenConfirmDialog(false)
|
||||||
|
setOpenDispatchDialog(false)
|
||||||
|
setOpenCancelDialog(false)
|
||||||
|
setOpenDeliveredDialog(false) // Close delivered dialog
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCancel = async () => {
|
||||||
|
setOpenConfirmDialog(false)
|
||||||
|
setOpenDispatchDialog(false)
|
||||||
|
setOpenCancelDialog(false)
|
||||||
|
setOpenDeliveredDialog(false) // Close delivered dialog
|
||||||
|
}
|
||||||
|
const handlePartialOrderClose = () => {
|
||||||
|
setOpnePartialModal(false)
|
||||||
|
}
|
||||||
|
const handlePartialProcess = async (availability) => {
|
||||||
|
console.log(availability)
|
||||||
|
const prepareData = availability
|
||||||
|
.filter(({ processquantity }) => processquantity > 0)
|
||||||
|
.map(
|
||||||
|
({
|
||||||
|
productId,
|
||||||
|
SKU,
|
||||||
|
name,
|
||||||
|
categoryName,
|
||||||
|
brandName,
|
||||||
|
price,
|
||||||
|
GST,
|
||||||
|
HSN_Code,
|
||||||
|
description,
|
||||||
|
processquantity,
|
||||||
|
}) => ({
|
||||||
|
productId: productId,
|
||||||
|
SKU,
|
||||||
|
name,
|
||||||
|
categoryName,
|
||||||
|
brandName,
|
||||||
|
price,
|
||||||
|
GST,
|
||||||
|
HSN_Code,
|
||||||
|
description,
|
||||||
|
processquantity,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const cancellationRes = await Axios.post(
|
||||||
|
`/api/pd-process-order`,
|
||||||
|
{
|
||||||
|
invoiceItems: prepareData,
|
||||||
|
orderId: id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
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')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const timelineData = [
|
||||||
|
{ event: 'Order Placed On', date: order?.createdAt },
|
||||||
|
{
|
||||||
|
event: 'Processing Started',
|
||||||
|
date: order?.status_timeline?.processing || '-',
|
||||||
|
},
|
||||||
|
{ event: 'Dispatched On', date: order?.status_timeline?.dispatched || '-' },
|
||||||
|
{ event: 'Delivered On', date: order?.status_timeline?.delivered || '-' },
|
||||||
|
]
|
||||||
|
|
||||||
|
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(-1)} 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">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
|
||||||
|
const totalWithGST = subtotal + gstAmount
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow key={index}>
|
||||||
|
<TableCell>
|
||||||
|
<img
|
||||||
|
src={item.productId.image}
|
||||||
|
alt={item.productId.name}
|
||||||
|
style={{
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
marginRight: 10,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Typography variant="subtitle1">{item.productId.name}</Typography>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="right">₹{item.price}</TableCell>
|
||||||
|
<TableCell align="right">{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 Itmes to processed
|
||||||
|
</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 item sm={6} md={6} xl={6}>
|
||||||
|
<TableContainer
|
||||||
|
component={Paper}
|
||||||
|
sx={{ maxWidth: 600, margin: "auto", mt: 4 }}
|
||||||
|
>
|
||||||
|
<Table
|
||||||
|
sx={{
|
||||||
|
background: "#3c4b64",
|
||||||
|
color: "white",
|
||||||
|
fontWeight: "bold",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TableHead sx={{ padding: "1rem" }}>
|
||||||
|
<TableRow sx={{ padding: "1rem" }}>
|
||||||
|
Status timeline
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{timelineData.map((row, index) => (
|
||||||
|
<TableRow
|
||||||
|
sx={{ color: "white", fontWeight: "bold" }}
|
||||||
|
key={index}
|
||||||
|
>
|
||||||
|
<TableCell
|
||||||
|
sx={{ color: "white", fontWeight: "bold" }}
|
||||||
|
>
|
||||||
|
{row.event}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell
|
||||||
|
sx={{ color: "white", fontWeight: "bold" }}
|
||||||
|
align="right"
|
||||||
|
>
|
||||||
|
{row.date !== "-" ? (
|
||||||
|
<>
|
||||||
|
{new Date(row.date).toDateString()}
|
||||||
|
<span>, {formatAMPM(row.date)}</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
"-"
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
</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' }}>
|
||||||
|
Customer Details
|
||||||
|
</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={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>
|
||||||
|
{order?.status !== 'cancelled' && order?.status !== 'delivered' && (
|
||||||
|
<FormControl fullWidth sx={{ mt: 2 }}>
|
||||||
|
<select className="form-control" onChange={handleStatusChange} value={orderStatus}>
|
||||||
|
{status === 'new' && (
|
||||||
|
<>
|
||||||
|
<option value="">New</option>
|
||||||
|
<option value="processing">Processing</option>
|
||||||
|
<option value="partial-processing">Partial Processing</option>
|
||||||
|
<option value="cancelled">Cancelled</option>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{status === 'pending' && (
|
||||||
|
<>
|
||||||
|
<option value="">Pending</option>
|
||||||
|
<option value="processing">Processing</option>
|
||||||
|
<option value="partial-processing">Partial Processing</option>
|
||||||
|
<option value="cancelled">Cancelled</option>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{status === 'processing' && (
|
||||||
|
<>
|
||||||
|
<option value="">Processing</option>
|
||||||
|
<option value="dispatched">Dispatch</option>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{status === 'dispatched' && (
|
||||||
|
<>
|
||||||
|
<option value="">Dispatch</option>
|
||||||
|
<option value="delivered">Delivered</option>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{orderStatus && (
|
||||||
|
<Button variant="contained" color="primary" onClick={handleUpdateClick} sx={{ mt: 2 }}>
|
||||||
|
Update Status
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* Dialogs for updating status */}
|
||||||
|
<Dialog open={openConfirmDialog} onClose={handleCancel}>
|
||||||
|
<DialogTitle>Update Order Status</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText>
|
||||||
|
Are you sure you want to update the status to {orderStatus}?
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handleCancel} variant="outlined" color="primary">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleConfirmUpdate} variant="contained" color="success" autoFocus>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
{/* Dialog for dispatch details */}
|
||||||
|
<Dialog open={openDispatchDialog} onClose={handleCancel}>
|
||||||
|
<DialogTitle>Dispatch Details</DialogTitle>
|
||||||
|
<form onSubmit={handleConfirmUpdate}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText>Please provide courier name and ID for dispatch:</DialogContentText>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
required
|
||||||
|
margin="dense"
|
||||||
|
label="Courier Name"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={courierName}
|
||||||
|
onChange={(e) => setCourierName(e.target.value)}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
margin="dense"
|
||||||
|
label="Courier ID"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={courierId}
|
||||||
|
onChange={(e) => setCourierId(e.target.value)}
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handleCancel} color="primary">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button type="submit" variant="contained" color="success" autoFocus>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</form>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
{/* Dialog for cancellation reason */}
|
||||||
|
<Dialog open={openCancelDialog} onClose={handleCancel}>
|
||||||
|
<DialogTitle>Cancellation Reason</DialogTitle>
|
||||||
|
<form onSubmit={handleConfirmUpdate}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText>Please provide a reason for cancelling the order:</DialogContentText>
|
||||||
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
required
|
||||||
|
margin="dense"
|
||||||
|
label="Cancellation Reason"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={cancellationReason}
|
||||||
|
onChange={(e) => setCancellationReason(e.target.value)}
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handleCancel} color="primary">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button type="submit" variant="contained" color="success" autoFocus>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</form>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
{/* Dialog for delivery confirmation */}
|
||||||
|
<Dialog open={openDeliveredDialog} onClose={handleCancel}>
|
||||||
|
<DialogTitle>Confirm Delivery</DialogTitle>
|
||||||
|
<form onSubmit={handleConfirmUpdate}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText>Please confirm the delivery details:</DialogContentText>
|
||||||
|
<FormControl required>
|
||||||
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
required
|
||||||
|
margin="dense"
|
||||||
|
label="Delivery Date"
|
||||||
|
type="date"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={deliveryDate}
|
||||||
|
onChange={(e) => setDeliveryDate(e.target.value)}
|
||||||
|
InputLabelProps={{
|
||||||
|
shrink: true,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handleCancel} variant="outlined" color="primary">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleConfirmUpdate} variant="contained" color="success" autoFocus>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</form>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
{/* partial processing */}
|
||||||
|
<OrderDetailsDialog
|
||||||
|
open={parialModal}
|
||||||
|
onClose={handlePartialOrderClose}
|
||||||
|
order={order}
|
||||||
|
onSubmit={handlePartialProcess}
|
||||||
|
/>
|
||||||
|
</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 ViewOrders
|
Loading…
Reference in New Issue
Block a user