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,
|
||||
// name: 'Stock',
|
||||
// to: '/stock',
|
||||
// icon: <CIcon icon={cilStorage} customClassName="nav-icon" />,
|
||||
// },
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'Opening inventory',
|
||||
to: '/stock',
|
||||
icon: <CIcon icon={cilStorage} customClassName="nav-icon" />,
|
||||
},
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'Announcements',
|
||||
|
@ -1,266 +1,144 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import {
|
||||
TableContainer,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
TableCell,
|
||||
TableBody,
|
||||
Paper,
|
||||
TextField,
|
||||
Button,
|
||||
Typography,
|
||||
TablePagination,
|
||||
Skeleton,
|
||||
TextField,
|
||||
MenuItem,
|
||||
Select,
|
||||
FormControl,
|
||||
InputLabel,
|
||||
Grid,
|
||||
Button,
|
||||
Box,
|
||||
} from '@mui/material'
|
||||
import axios from 'axios'
|
||||
import { isAutheticated } from '../../../auth'
|
||||
import Axios from '../../../axios'
|
||||
import Swal from 'sweetalert2'
|
||||
|
||||
function StockTable({ apiEndpoint, totalProducts }) {
|
||||
const [stocks, setStocks] = useState([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [page, setPage] = useState(0)
|
||||
function StockTable() {
|
||||
const [stocks, setStocks] = useState([]) // Store stock data
|
||||
const [loading, setLoading] = useState(true) // Loading state
|
||||
const [rowsPerPage, setRowsPerPage] = useState(5)
|
||||
const [category, setCategory] = useState('')
|
||||
const [brand, setBrand] = useState('')
|
||||
const [productName, setProductName] = useState('')
|
||||
const [isInitialStockMode, setIsInitialStockMode] = useState(false)
|
||||
const [initialStock, setInitialStock] = useState([])
|
||||
const [products, setProducts] = useState()
|
||||
const [page, setPage] = useState(0)
|
||||
const token = isAutheticated()
|
||||
|
||||
console.log(initialStock, 'initial stock ')
|
||||
|
||||
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
|
||||
// Fetch stock data from the backend
|
||||
const fetchStocks = async () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
const response = await axios.get(apiEndpoint, {
|
||||
params: { category, brand, productName, page, limit: rowsPerPage },
|
||||
const response = await Axios.get('/api/pd/stock', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
setStocks(response.data.stocks)
|
||||
setStocks(response.data.stocks || [])
|
||||
} catch (error) {
|
||||
console.error('Error fetching products:', error)
|
||||
console.error('Error fetching stocks:', error)
|
||||
} finally {
|
||||
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 handleChangeRowsPerPage = (event) => {
|
||||
setRowsPerPage(parseInt(event.target.value, 10))
|
||||
setPage(0)
|
||||
}
|
||||
|
||||
const handleStockChange = (productId, value) => {
|
||||
setInitialStock((prevStock) => {
|
||||
const stockExists = prevStock.find((item) => item.productId === productId)
|
||||
|
||||
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
|
||||
// Fetch stocks on component mount
|
||||
useEffect(() => {
|
||||
fetchStocks()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div style={{ background: '#fff', padding: '1rem' }}>
|
||||
{!stockExists && !isInitialStockMode ? (
|
||||
<Button variant="contained" onClick={() => setIsInitialStockMode(true)}>
|
||||
Add Initial Stock
|
||||
<Box p={3}>
|
||||
<Typography variant="h5" mb={2}>
|
||||
Product Stock Management
|
||||
</Typography>
|
||||
<TableContainer component={Paper}>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Product Name</TableCell>
|
||||
<TableCell>SKU</TableCell>
|
||||
<TableCell>Current Stock</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{loading ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={3} align="center">
|
||||
<Typography>Loading...</Typography>
|
||||
</TableCell>
|
||||
</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>
|
||||
</Table>
|
||||
<TablePagination
|
||||
component="div"
|
||||
count={stocks.length}
|
||||
page={page}
|
||||
onPageChange={handleChangePage}
|
||||
rowsPerPage={rowsPerPage}
|
||||
onRowsPerPageChange={handleChangeRowsPerPage}
|
||||
/>
|
||||
</TableContainer>
|
||||
<Box mt={2} display="flex" justifyContent="flex-end">
|
||||
<Button variant="contained" color="primary" onClick={handleSubmit}>
|
||||
Update Stock
|
||||
</Button>
|
||||
) : isInitialStockMode ? (
|
||||
<>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
Add Initial Stock
|
||||
</Typography>
|
||||
<TableContainer component={Paper}>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Product Name</TableCell>
|
||||
<TableCell>SKU</TableCell>
|
||||
<TableCell>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>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{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>
|
||||
<TableCell colSpan={7} align="center">
|
||||
<Typography variant="body1">Data not found</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<TablePagination
|
||||
rowsPerPageOptions={[5, 10, 25]}
|
||||
component="div"
|
||||
count={totalProducts}
|
||||
rowsPerPage={rowsPerPage}
|
||||
page={page}
|
||||
onPageChange={handleChangePage}
|
||||
onRowsPerPageChange={handleChangeRowsPerPage}
|
||||
/>
|
||||
</TableContainer>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user