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',
|
||||
icon: <CIcon icon={cilDescription} customClassName="nav-icon" />,
|
||||
},
|
||||
|
||||
// {
|
||||
// component: CNavTitle,
|
||||
// name: 'Theme',
|
||||
// },
|
||||
// {
|
||||
// component: CNavItem,
|
||||
// name: 'Colors',
|
||||
// to: '/theme/colors',
|
||||
// icon: <CIcon icon={cilDrop} customClassName="nav-icon" />,
|
||||
// },
|
||||
// {
|
||||
// component: CNavItem,
|
||||
// name: 'Typography',
|
||||
// to: '/theme/typography',
|
||||
// icon: <CIcon icon={cilPencil} customClassName="nav-icon" />,
|
||||
// },
|
||||
// {
|
||||
// component: CNavTitle,
|
||||
// name: 'Components',
|
||||
// },
|
||||
// {
|
||||
// component: CNavGroup,
|
||||
// name: 'Base',
|
||||
// to: '/base',
|
||||
// icon: <CIcon icon={cilPuzzle} customClassName="nav-icon" />,
|
||||
// items: [
|
||||
// {
|
||||
// component: CNavItem,
|
||||
// name: 'Accordion',
|
||||
// to: '/base/accordion',
|
||||
// },
|
||||
// {
|
||||
// component: CNavItem,
|
||||
// name: 'Breadcrumb',
|
||||
// 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,
|
||||
name: 'RD Orders',
|
||||
to: '/base',
|
||||
icon: <CIcon icon={cilPuzzle} customClassName="nav-icon" />,
|
||||
items: [
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'New',
|
||||
to: '/new',
|
||||
},
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'Pending',
|
||||
to: '/pending',
|
||||
},
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'Processing',
|
||||
to: '/processing',
|
||||
},
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'Dispathed',
|
||||
to: '/dispatched',
|
||||
},
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'Delivered',
|
||||
to: '/delivered',
|
||||
},
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'Cancelled',
|
||||
to: 'cancelled',
|
||||
},
|
||||
],
|
||||
},
|
||||
// {
|
||||
// component: CNavGroup,
|
||||
// name: 'Buttons',
|
||||
|
@ -5,6 +5,11 @@ import Cart from './views/pages/cart/cart'
|
||||
import OrderDetails from './views/orders/OrderDetails'
|
||||
import ProductManual from './views/pages/productManual/productManual'
|
||||
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 Shop = React.lazy(() => import('./views/shops/Shop'))
|
||||
@ -27,6 +32,11 @@ const routes = [
|
||||
// Product manual
|
||||
{ path: '/product-manual', name: 'Product Manual ', element: ProductManual },
|
||||
{ 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: '/change-password', name: 'Change password', element: ChangePassword },
|
||||
|
@ -57,6 +57,7 @@ const Order = () => {
|
||||
limit: rowsPerPage, // number of rows per page
|
||||
},
|
||||
})
|
||||
console.log('total orders ', response)
|
||||
setOrders(response.data.plcaedOrders)
|
||||
setTotalOrders(response.data.totalOrders) // Ensure the API returns the total count of orders
|
||||
} catch (error) {
|
||||
|
@ -193,37 +193,6 @@ const OrderDetails = () => {
|
||||
</Grid>
|
||||
</Grid>
|
||||
</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>
|
||||
)
|
||||
}
|
||||
|
@ -104,6 +104,7 @@ const Login = () => {
|
||||
console.log(res)
|
||||
if (res.data.success === true && res.data.user.role === 'principal-Distributor') {
|
||||
localStorage.setItem('authToken', res.data.token)
|
||||
console.log(res.data.token)
|
||||
dispatch(clearCart())
|
||||
navigate('/dashboard')
|
||||
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