stock done
Some checks failed
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 (17.x, windows-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 (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 (17.x, windows-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
b96f7832e2
commit
2891b634a2
12
src/_nav.js
12
src/_nav.js
@ -102,12 +102,12 @@ const _nav = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// component: CNavItem,
|
component: CNavItem,
|
||||||
// name: 'Stock',
|
name: 'Opening inventory',
|
||||||
// to: '/stock',
|
to: '/stock',
|
||||||
// icon: <CIcon icon={cilStorage} customClassName="nav-icon" />,
|
icon: <CIcon icon={cilStorage} customClassName="nav-icon" />,
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
component: CNavItem,
|
component: CNavItem,
|
||||||
name: 'Announcements',
|
name: 'Announcements',
|
||||||
|
@ -1,131 +1,93 @@
|
|||||||
import React, { useState, useEffect } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import {
|
import {
|
||||||
TableContainer,
|
|
||||||
Table,
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableContainer,
|
||||||
TableHead,
|
TableHead,
|
||||||
TableRow,
|
TableRow,
|
||||||
TableCell,
|
|
||||||
TableBody,
|
|
||||||
Paper,
|
Paper,
|
||||||
|
TextField,
|
||||||
|
Button,
|
||||||
Typography,
|
Typography,
|
||||||
TablePagination,
|
TablePagination,
|
||||||
Skeleton,
|
Box,
|
||||||
TextField,
|
|
||||||
MenuItem,
|
|
||||||
Select,
|
|
||||||
FormControl,
|
|
||||||
InputLabel,
|
|
||||||
Grid,
|
|
||||||
Button,
|
|
||||||
} from '@mui/material'
|
} from '@mui/material'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
import { isAutheticated } from '../../../auth'
|
||||||
import Axios from '../../../axios'
|
import Axios from '../../../axios'
|
||||||
|
import Swal from 'sweetalert2'
|
||||||
|
|
||||||
function StockTable({ apiEndpoint, totalProducts }) {
|
function StockTable() {
|
||||||
const [stocks, setStocks] = useState([])
|
const [stocks, setStocks] = useState([]) // Store stock data
|
||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true) // Loading state
|
||||||
const [page, setPage] = useState(0)
|
|
||||||
const [rowsPerPage, setRowsPerPage] = useState(5)
|
const [rowsPerPage, setRowsPerPage] = useState(5)
|
||||||
const [category, setCategory] = useState('')
|
const [page, setPage] = useState(0)
|
||||||
const [brand, setBrand] = useState('')
|
const token = isAutheticated()
|
||||||
const [productName, setProductName] = useState('')
|
|
||||||
const [isInitialStockMode, setIsInitialStockMode] = useState(false)
|
|
||||||
const [initialStock, setInitialStock] = useState([])
|
|
||||||
const [products, setProducts] = useState()
|
|
||||||
|
|
||||||
console.log(initialStock, 'initial stock ')
|
// Fetch stock data from the backend
|
||||||
|
|
||||||
const fetchProducts = async () => {
|
|
||||||
try {
|
|
||||||
const response = await Axios.get('/api/product/getAll/user/')
|
|
||||||
setProducts(response.data?.products || [])
|
|
||||||
console.log(response, 'resp of products ')
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
}
|
|
||||||
const response = await Axios.get('/api/product/getAll/user/')
|
|
||||||
setProducts(response.data?.products || [])
|
|
||||||
}
|
|
||||||
// Fetch Products from Backend API
|
|
||||||
const fetchStocks = async () => {
|
const fetchStocks = async () => {
|
||||||
setLoading(true)
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(apiEndpoint, {
|
const response = await Axios.get('/api/pd/stock', {
|
||||||
params: { category, brand, productName, page, limit: rowsPerPage },
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
})
|
})
|
||||||
setStocks(response.data.stocks)
|
setStocks(response.data.stocks || [])
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching products:', error)
|
console.error('Error fetching stocks:', error)
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
useEffect(() => {
|
|
||||||
fetchProducts()
|
|
||||||
}, [])
|
|
||||||
useEffect(() => {
|
|
||||||
fetchStocks()
|
|
||||||
}, [category, brand, productName, page, rowsPerPage])
|
|
||||||
|
|
||||||
// Pagination Handlers
|
// Handle stock value change and persist across pagination
|
||||||
|
const handleStockChange = (productId, value) => {
|
||||||
|
setStocks((prevStocks) =>
|
||||||
|
prevStocks.map((stock) =>
|
||||||
|
stock.productid === productId ? { ...stock, Stock: parseInt(value, 10) || 0 } : stock,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
console.log(stocks, 'stocks')
|
||||||
|
|
||||||
|
// Submit updated stock values
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
try {
|
||||||
|
await Axios.put(
|
||||||
|
'/api/pd/stock-update',
|
||||||
|
{ products: stocks },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
Swal.fire('success!', 'Stock updated successfully', 'success')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updating stock:', error)
|
||||||
|
Swal.fire('error!', 'Something went wrong', 'error')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pagination handlers
|
||||||
const handleChangePage = (event, newPage) => setPage(newPage)
|
const handleChangePage = (event, newPage) => setPage(newPage)
|
||||||
const handleChangeRowsPerPage = (event) => {
|
const handleChangeRowsPerPage = (event) => {
|
||||||
setRowsPerPage(parseInt(event.target.value, 10))
|
setRowsPerPage(parseInt(event.target.value, 10))
|
||||||
setPage(0)
|
setPage(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleStockChange = (productId, value) => {
|
// Fetch stocks on component mount
|
||||||
setInitialStock((prevStock) => {
|
useEffect(() => {
|
||||||
const stockExists = prevStock.find((item) => item.productId === productId)
|
fetchStocks()
|
||||||
|
}, [])
|
||||||
if (stockExists) {
|
|
||||||
// Update the existing stock entry
|
|
||||||
return prevStock.map((item) =>
|
|
||||||
item.productId === productId ? { ...item, stock: value } : item,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// Add a new stock entry
|
|
||||||
return [...prevStock, { productId, stock: value }]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSubmitInitialStock = async () => {
|
|
||||||
try {
|
|
||||||
await axios.post(`${apiEndpoint}/initial-stock`, { stock: initialStock })
|
|
||||||
setIsInitialStockMode(false)
|
|
||||||
fetchProducts()
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error adding initial stock:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const formatDateTime = (dateString) => {
|
|
||||||
const date = new Date(dateString)
|
|
||||||
return `${date.toDateString()}, ${formatAMPM(date)}`
|
|
||||||
}
|
|
||||||
|
|
||||||
const formatAMPM = (date) => {
|
|
||||||
let hours = date.getHours()
|
|
||||||
const minutes = date.getMinutes()
|
|
||||||
const ampm = hours >= 12 ? 'PM' : 'AM'
|
|
||||||
hours = hours % 12 || 12
|
|
||||||
return `${hours}:${minutes < 10 ? '0' + minutes : minutes} ${ampm}`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if stock exists
|
|
||||||
const stockExists = stocks.length > 0
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ background: '#fff', padding: '1rem' }}>
|
<Box p={3}>
|
||||||
{!stockExists && !isInitialStockMode ? (
|
<Typography variant="h5" mb={2}>
|
||||||
<Button variant="contained" onClick={() => setIsInitialStockMode(true)}>
|
Product Stock Management
|
||||||
Add Initial Stock
|
|
||||||
</Button>
|
|
||||||
) : isInitialStockMode ? (
|
|
||||||
<>
|
|
||||||
<Typography variant="h6" gutterBottom>
|
|
||||||
Add Initial Stock
|
|
||||||
</Typography>
|
</Typography>
|
||||||
<TableContainer component={Paper}>
|
<TableContainer component={Paper}>
|
||||||
<Table>
|
<Table>
|
||||||
@ -133,134 +95,50 @@ function StockTable({ apiEndpoint, totalProducts }) {
|
|||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell>Product Name</TableCell>
|
<TableCell>Product Name</TableCell>
|
||||||
<TableCell>SKU</TableCell>
|
<TableCell>SKU</TableCell>
|
||||||
<TableCell>Stock</TableCell>
|
<TableCell>Current Stock</TableCell>
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>
|
|
||||||
{products.map((product) => (
|
|
||||||
<TableRow key={product._id}>
|
|
||||||
<TableCell>{product.name}</TableCell>
|
|
||||||
<TableCell>{product.SKU}</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
<TextField
|
|
||||||
type="number"
|
|
||||||
value={
|
|
||||||
initialStock.find((item) => item.productId === product._id)?.stock || ''
|
|
||||||
}
|
|
||||||
onChange={(e) => handleStockChange(product._id, e.target.value)}
|
|
||||||
/>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</TableContainer>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
|
||||||
onClick={handleSubmitInitialStock}
|
|
||||||
sx={{ marginTop: 2 }}
|
|
||||||
>
|
|
||||||
Submit Stock
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{/* Filter Controls */}
|
|
||||||
<Grid container spacing={2} sx={{ marginBottom: 2 }}>
|
|
||||||
<Grid item xs={12} md={4}>
|
|
||||||
<FormControl fullWidth>
|
|
||||||
<InputLabel>Category</InputLabel>
|
|
||||||
<Select
|
|
||||||
value={category}
|
|
||||||
onChange={(e) => setCategory(e.target.value)}
|
|
||||||
label="Category"
|
|
||||||
>
|
|
||||||
<MenuItem value="">All</MenuItem>
|
|
||||||
<MenuItem value="Electronics">Electronics</MenuItem>
|
|
||||||
<MenuItem value="Clothing">Clothing</MenuItem>
|
|
||||||
<MenuItem value="Furniture">Furniture</MenuItem>
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} md={4}>
|
|
||||||
<FormControl fullWidth>
|
|
||||||
<InputLabel>Brand</InputLabel>
|
|
||||||
<Select value={brand} onChange={(e) => setBrand(e.target.value)} label="Brand">
|
|
||||||
<MenuItem value="">All</MenuItem>
|
|
||||||
<MenuItem value="Apple">Apple</MenuItem>
|
|
||||||
<MenuItem value="Nike">Nike</MenuItem>
|
|
||||||
<MenuItem value="Ikea">Ikea</MenuItem>
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} md={4}>
|
|
||||||
<TextField
|
|
||||||
fullWidth
|
|
||||||
label="Product Name"
|
|
||||||
value={productName}
|
|
||||||
onChange={(e) => setProductName(e.target.value)}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
{/* Products Table */}
|
|
||||||
<TableContainer component={Paper}>
|
|
||||||
<Table>
|
|
||||||
<TableHead>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell>Product Name</TableCell>
|
|
||||||
<TableCell>SKU</TableCell>
|
|
||||||
<TableCell>Category</TableCell>
|
|
||||||
<TableCell>Brand</TableCell>
|
|
||||||
<TableCell>Added On</TableCell>
|
|
||||||
<TableCell>Price</TableCell>
|
|
||||||
<TableCell>Stock</TableCell>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
Array.from(new Array(rowsPerPage)).map((_, index) => (
|
|
||||||
<TableRow key={index}>
|
|
||||||
<TableCell colSpan={7}>
|
|
||||||
<Skeleton height={40} />
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
))
|
|
||||||
) : stocks.length > 0 ? (
|
|
||||||
products.map((product) => (
|
|
||||||
<TableRow key={product._id}>
|
|
||||||
<TableCell>{product.name}</TableCell>
|
|
||||||
<TableCell>{product.sku}</TableCell>
|
|
||||||
<TableCell>{product.categoryName}</TableCell>
|
|
||||||
<TableCell>{product.brandName}</TableCell>
|
|
||||||
<TableCell>{formatDateTime(product.addedOn)}</TableCell>
|
|
||||||
<TableCell>{product.price.toFixed(2)}</TableCell>
|
|
||||||
<TableCell>{product.stock}</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={7} align="center">
|
<TableCell colSpan={3} align="center">
|
||||||
<Typography variant="body1">Data not found</Typography>
|
<Typography>Loading...</Typography>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
) : (
|
||||||
|
stocks.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((stock) => (
|
||||||
|
<TableRow key={stock.productid}>
|
||||||
|
<TableCell>{stock.name}</TableCell>
|
||||||
|
<TableCell>{stock.SKU}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<TextField
|
||||||
|
type="number"
|
||||||
|
value={stock.Stock}
|
||||||
|
onChange={(e) => handleStockChange(stock.productid, e.target.value)}
|
||||||
|
variant="outlined"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
)}
|
)}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
<TablePagination
|
<TablePagination
|
||||||
rowsPerPageOptions={[5, 10, 25]}
|
|
||||||
component="div"
|
component="div"
|
||||||
count={totalProducts}
|
count={stocks.length}
|
||||||
rowsPerPage={rowsPerPage}
|
|
||||||
page={page}
|
page={page}
|
||||||
onPageChange={handleChangePage}
|
onPageChange={handleChangePage}
|
||||||
|
rowsPerPage={rowsPerPage}
|
||||||
onRowsPerPageChange={handleChangeRowsPerPage}
|
onRowsPerPageChange={handleChangeRowsPerPage}
|
||||||
/>
|
/>
|
||||||
</TableContainer>
|
</TableContainer>
|
||||||
</>
|
<Box mt={2} display="flex" justifyContent="flex-end">
|
||||||
)}
|
<Button variant="contained" color="primary" onClick={handleSubmit}>
|
||||||
</div>
|
Update Stock
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user