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

This commit is contained in:
ROSHAN GARG 2024-09-27 10:58:56 +05:30
parent 91337d2b3f
commit 03dbed7d14
13 changed files with 2030 additions and 135 deletions

View File

@ -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',

View File

@ -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 },

View File

@ -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) {

View File

@ -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>
) )
} }

View File

@ -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)

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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