I have the father which is Productos and a child called EditarProductos. I want to pass producto.id to EditarProductos.
Here is Productos:
import {Button, TableHead, TableRow, TableCell, TableBody, Table} from '#material-ui/core'
import { withStyles, makeStyles } from '#material-ui/core/styles';
import InsertarProductos from './InsertarProductos';
import Grid from '#material-ui/core/Grid';
import EditIcon from '#material-ui/icons/Edit';
import DeleteIcon from '#material-ui/icons/Delete';
import EditarProductos from './EditarProductos';
const StyledTableCell = withStyles((theme) => ({
head: {
backgroundColor: theme.palette.common.black,
color: theme.palette.common.white,
},
body: {
fontSize: 14,
},
}))(TableCell);
const StyledTableRow = withStyles((theme) => ({
root: {
'&:nth-of-type(odd)': {
backgroundColor: theme.palette.background.default,
},
},
}))(TableRow);
function Productos(props) {
const [productos, setProductos] = useState([]);
var id='';
useEffect(() => {
const getProductos = async () => {
const res = await fetch("/productos", {
method: 'GET',
headers: {'Content-Type': 'application/json'},
})
//console.log(res);
const response = await res.json();
setProductos(response);
}
getProductos();
})
function editar(producto){
console.log("entro 1");
//console.log(producto.id);
id = producto.id;
console.log(id);
return <EditarProductos productoEdit = {id}/>;
}
function eliminar(producto){
console.log(producto.id);
id=producto.id;
deleteProductos();
window.location.reload();
}
const deleteProductos = async () => {
console.log("entro");
console.log(id);
const res = await fetch("/productos", {
method: 'DELETE',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
id: id
})
})
const response = await res.json();
}
const useStyles = makeStyles({
table: {
minWidth: 700,
},
});
//console.log(plot);
const mystlye = {
minWidth: "50%",
minHeight: 50
};
//
const classes = useStyles();
return (
<div>
<br />
<Grid container spacing={3}>
<Grid item xs={3}></Grid>
<Grid item xs={3}></Grid>
<Grid item xs={3}></Grid>
<Grid item xs={3}>
<InsertarProductos productoInsert="fer"/>
</Grid>
</Grid>
<br />
<Table className={classes.table}>
<TableHead>
<TableRow>
<StyledTableCell>ID</StyledTableCell>
<StyledTableCell>Nombre</StyledTableCell>
<StyledTableCell>Precio de Compra</StyledTableCell>
<StyledTableCell>Precio de Venta</StyledTableCell>
<StyledTableCell>Cantidad</StyledTableCell>
<StyledTableCell>Categoria</StyledTableCell>
<StyledTableCell>Extras</StyledTableCell>
</TableRow>
</TableHead>
<TableBody>
{productos.map((producto) =>
<TableRow className="data-row">
<StyledTableCell>{producto.id}</StyledTableCell>
<StyledTableCell>{producto.nombre}</StyledTableCell>
<StyledTableCell>{producto.precio_compra}</StyledTableCell>
<StyledTableCell>{producto.precio_venta}</StyledTableCell>
<StyledTableCell>{producto.cantidad}</StyledTableCell>
<StyledTableCell>{producto.categorias_id}</StyledTableCell>
<StyledTableCell>
<Button variant="outlined" onClick={() => editar(producto)}>
<EditIcon />
</Button>
<Button variant="outlined" onClick={() => eliminar(producto)} ><DeleteIcon /> </Button>
</StyledTableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
);
}
export default Productos;
If I try to pass the id inside the button, it starts to print the id multiple times like in a loop.
EditarProductos is never reached and the id isn't passed. Could someone help me fix my problem, please?
PD: In EditarProductos I'm trying to print id like this:
console.log(props.productoEdit);
You can't return (and render) UI elements like this. You can rather set the id of a product to display though. Using the is you can conditionally render EditarProductos into the UI. You'll likely also want/need a way to reset this when the dialog is dismissed/closed.
The following is one way to do this:
function Productos(props) {
const [productos, setProductos] = useState([]);
const [id, setId] = useState(null); // create state variable
...
function editar(producto){
console.log("entro 1");
console.log(producto.id);
setId(producto.id);
}
function onEditarClose() {
setId(null);
}
...
return (
<div>
{id &&
// conditionally render in UI the dialog
<EditarProductos onClose={onEditarClose} productoEdit={id} />
}
<br />
<Grid container spacing={3}>
<Grid item xs={3}></Grid>
<Grid item xs={3}></Grid>
<Grid item xs={3}></Grid>
<Grid item xs={3}>
<InsertarProductos productoInsert="fer"/>
</Grid>
</Grid>
<br />
<Table className={classes.table}>
<TableHead>
<TableRow>
<StyledTableCell>ID</StyledTableCell>
<StyledTableCell>Nombre</StyledTableCell>
<StyledTableCell>Precio de Compra</StyledTableCell>
<StyledTableCell>Precio de Venta</StyledTableCell>
<StyledTableCell>Cantidad</StyledTableCell>
<StyledTableCell>Categoria</StyledTableCell>
<StyledTableCell>Extras</StyledTableCell>
</TableRow>
</TableHead>
<TableBody>
{productos.map((producto) =>
<TableRow className="data-row">
<StyledTableCell>{producto.id}</StyledTableCell>
<StyledTableCell>{producto.nombre}</StyledTableCell>
<StyledTableCell>{producto.precio_compra}</StyledTableCell>
<StyledTableCell>{producto.precio_venta}</StyledTableCell>
<StyledTableCell>{producto.cantidad}</StyledTableCell>
<StyledTableCell>{producto.categorias_id}</StyledTableCell>
<StyledTableCell>
<Button variant="outlined" onClick={() => editar(producto)}>
<EditIcon />
</Button>
<Button variant="outlined" onClick={() => eliminar(producto)} ><DeleteIcon /> </Button>
</StyledTableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
);
}
Related
import React, { useState, useEffect, Fragment } from "react";
import classes from "../CSS/DataUpload.module.css";
import * as XLSX from "xlsx";
import axios from "axios";
import Table from "#mui/material/Table";
import TableBody from "#mui/material/TableBody";
import TableCell from "#mui/material/TableCell";
import TableContainer from "#mui/material/TableContainer";
import TableHead from "#mui/material/TableHead";
import TableRow from "#mui/material/TableRow";
import Paper from "#mui/material/Paper";
import { Button } from "#mui/material";
let initialSend = true;
const DataUpload = () => {
const [sendData, setSendData] = useState([]);
const [addData, setAddData] = useState(false);
const [display, setDisplay] = useState(false);
const [notification, setNotification] = useState();
useEffect(() => {
// console.log(sendData);
// let payload = JSON.parse(sendData);
// console.log("type of ", typeof payload);
const excelData = async () => {
// console.log(se)
try {
console.log(sendData);
const url = "http://localhost:5000/users";
const config = {
"Content-Type": "application/json",
};
const response = await axios.post(url, sendData, config);
const msg = response.data.msg;
setNotification(msg);
} catch (error) {
console.log(error);
}
};
if (initialSend) {
initialSend = false;
return;
} else {
setDisplay(true);
excelData();
}
}, [addData]);
const onChange = (e) => {
const [file] = e.target.files;
const reader = new FileReader();
reader.onload = (evt) => {
const bstr = evt.target.result;
const wb = XLSX.read(bstr, { type: "binary" });
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
const data = XLSX.utils.sheet_to_json(ws, {
header: [
"no",
"name",
"vuln_type",
"summary",
"tech_details",
"remediation",
"req",
"res",
"cvss_score",
"cvss_eq",
"severity",
],
blankrows: false,
});
data.shift();
setSendData(data);
};
reader.readAsBinaryString(file);
};
const addDataHandler = () => {
setAddData(true);
};
const removeNotification = () => {
setDisplay(false);
};
// };
return (
<Fragment>
{display && (
<div
style={{
backgroundColor: "red",
marginLeft: "100px",
marginRight: "100px",
}}
>
<p style={{ color: "white" }}>{notification}</p>
<button
style={{ float: "right", color: "white" }}
onClick={removeNotification}
>
X
</button>
</div>
)}
<div className={classes.excelupload}>
<p>Choose Excel File to Upload</p>
<input type="file" id="input" onChange={onChange}></input>
</div>
<div style={{ margin: "50px" }}>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} size="small" aria-label="a dense table">
<TableHead>
<TableRow sx={{ fontSize: 16 }}>
<TableCell>No</TableCell>
<TableCell align="right">Name</TableCell>
<TableCell align="right">Vuln Type</TableCell>
<TableCell align="right">Summary</TableCell>
<TableCell align="right">Tech Details</TableCell>
<TableCell align="right">Remediation</TableCell>
<TableCell align="right">req</TableCell>
<TableCell align="right">res</TableCell>
<TableCell align="right">cvss score</TableCell>
<TableCell align="right">cvsseq</TableCell>
<TableCell align="right">severity</TableCell>
</TableRow>
</TableHead>
<TableBody>
{sendData.map((row) => (
<TableRow
key={row.no}
sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
>
<TableCell component="th" scope="row">
{row.no}
</TableCell>
<TableCell align="right">{row.name}</TableCell>
<TableCell align="right">{row.vuln_type}</TableCell>
<TableCell align="right">{row.summary}</TableCell>
<TableCell align="right">{row.tech_details}</TableCell>
<TableCell align="right">{row.remediation}</TableCell>
<TableCell align="right">{row.req}</TableCell>
<TableCell align="right">{row.res}</TableCell>
<TableCell align="right">{row.cvss_score}</TableCell>
<TableCell align="right">{row.cvss_eq}</TableCell>
<TableCell align="right">{row.severity}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</div>
</Fragment>
);
};
export default DataUpload;[enter image description here][1]
This the code for my front end. I want to add a collapse button to the request and response field. I have no idea about how to do it as I am a newbie in this field. I am making this project for our company. It fetches the data from MongoDB which is the back end. It would be really great if anyone can suggest how to do it. Thanks in advance.
You are looking for the Collapse component.
Just put your table into Collapse component, sth like ↓
const [open, setOpen] = useState(false);
return (
<>
<button onClick={() => setOpen(!open)}>
{open ? "Collapse" : "Expand"}
</button>
<Collapse in={open}>
<TableContainer component={Paper}>
....
</TableContainer>
</Collapse>
</>
)
Here is the demo I've created, you can take a look.
Update
I think you need sth like this example, horizontal collapse, am I right?
The example was not created by me though, I think it can give you some hints.
I'm working on a simple React app alongside TypeScript, and I'm using JSONPlaceholder for API calls simulation. I have implemented everything I need, but facing a problem when it comes to re-rendering components that shows response data from API. The thing is that if I do HTTP GET to all data after I do DELETE or PUT, I will again get all same data because data changes don't actually apply on the server.
I will appreciate it if you can help me how to edit my functions for DELETE and PUT.
When I console.log my responses inside components, I get staus ok 200, so the API call part is fine, the only thing that I struggle with is how to re-render components properly
There is a component that shows all data, and also make calls to DELETE endpoint, and shows modal where I call PUT endpoint:
const PostsTable: React.FunctionComponent = () => {
const [posts, setPosts] = useState<Array<IPost>>([]);
const [selectedPost, setSelectedPost] = useState<IPost>({});
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
const fetchPosts = () => {
PostService.getAllPosts()
.then((response: any) => {
setPosts(response.data);
})
.catch((e: Error) => {
console.log(e);
});
};
useEffect(() => {
fetchPosts();
}, []);
const editPost = (post: IPost) => (event: any) => {
setSelectedPost(post);
setDialogOpen(true);
};
const handleClose = () => {
setDialogOpen(false);
};
const deletePost =
(id: any): any =>
(event: Event) => {
event.stopPropagation();
PostService.deletePost(id)
.then((response: any) => {
setPosts(posts);
console.log(response);
})
.catch((e: Error) => {
console.log(e);
});
};
return (
<Container fixed>
{!posts || posts.length < 1 ? (
<div style={{ display: 'flex', justifyContent: 'center' }}>
<CircularProgress color="primary" size={100} />
</div>
) : (
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell align="left">User Id</TableCell>
<TableCell align="left">Post Id</TableCell>
<TableCell align="left">Title</TableCell>
<TableCell align="left">Actions</TableCell>
</TableRow>
</TableHead>
<TableBody>
{posts.map((post: IPost) => (
<TableRow
key={post.id}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell>{post.userId}</TableCell>
<TableCell align="left">{post.id}</TableCell>
<TableCell align="left">{post.title}</TableCell>
<TableCell align="left">
<Tooltip title="Delete">
<IconButton onClick={editPost(post)}>
<EditIcon />
</IconButton>
</Tooltip>
<Tooltip title="Edit">
<IconButton onClick={deletePost(post.id)}>
<DeleteIcon />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
)}
{
<EditPostDialog
open={dialogOpen}
handleClose={handleClose}
selectedPost={selectedPost}
/>
}
</Container>
);
};
export default PostsTable;
And also, there is a modal component with PUT function:
const EditPostDialog: React.FunctionComponent<IEditPostDialog> = (
props: IEditPostDialog
) => {
const { open, handleClose, selectedPost } = props;
const [post, setPost] = useState<IPost>({});
useEffect(() => {
const newPost = {
id: selectedPost.id,
userId: selectedPost.userId,
title: selectedPost.title,
body: selectedPost.body,
};
setPost(newPost);
}, [selectedPost]);
const handleChange = (event: any) => {
setPost({ ...post, [event.target.name]: event.target.value });
};
const handleSubmit = () => {
PostService.updatePost(post.id, post)
.then((response: any) => {
console.log(response);
})
.catch((e: Error) => {
console.log(e);
});
handleClose();
};
return (
<Dialog onClose={handleClose} open={open}>
<DialogTitle id="simple-dialog-title">Post info</DialogTitle>
<DialogContent classes={{ root: 'dialog-content' }}>
<TextField
id="userId"
label="User Id"
name="userId"
variant="outlined"
value={post.userId}
onChange={handleChange}
style={{ marginTop: 16 }}
/>
<TextField
id="title"
label="Title"
name="title"
variant="outlined"
value={post.title}
onChange={handleChange}
/>
<TextField
id="body"
label="Body"
name="body"
variant="outlined"
value={post.body}
onChange={handleChange}
multiline
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Close</Button>
<Button onClick={handleSubmit}>Submit</Button>
</DialogActions>
</Dialog>
);
};
export default EditPostDialog;
And at the end, my PostService.ts and HTTP files where is axios code to call API points:
const getAllPosts = () => {
return http.get<Array<IPost>>('/posts');
};
const getSinglePost = (id: number | undefined) => {
return http.get<IPost>(`/posts/${id}`);
};
const createPost = (data: IPost) => {
return http.post<IPost>('/posts', data);
};
const updatePost = (id: number | undefined, data: IPost) => {
return http.put<any>(`/posts/${id}`, data);
};
const deletePost = (id: number | undefined) => {
return http.delete<any>(`/posts/${id}`);
};
const PostService = {
getAllPosts,
getSinglePost,
createPost,
updatePost,
deletePost,
};
export default axios.create({
baseURL: 'https://jsonplaceholder.typicode.com',
headers: {
'Content-type': 'application/json',
},
});
Thank you all guys :)
Your delete function uses "setPosts(posts)" which I'm pretty sure is not what you meant. Also, your modal does not tell your main component that a post has been edited, I guess that's the problem ? Pass a callback to the modal to update the posts state in the main component.
I am using react-material-dashboard to view stats for the Admin.
I want to show all my users in a table to view in the admin dashboard. I am using Express to get the users from my DB but when I run in the browser I get a GET http://localhost:3001/api/fetchUsers 404 (Not Found) error.
How can I display all my users in my react-material-dashboard?
What am I doing wrong?
here is my structure:
CustomersListResults.js:
import { useState, useEffect } from 'react';
import PerfectScrollbar from 'react-perfect-scrollbar';
import {
Box,
Card,
Table,
TableCell,
TableHead,
TablePagination,
TableRow,
} from '#material-ui/core';
import Axios from 'axios';
const CustomerListResults = () => {
const [limit, setLimit] = useState(10);
const [page, setPage] = useState(0);
useEffect(() => {
Axios.get('http://localhost:3001/api/fetchUsers').then((response) => {
console.log(response);
});
}, []);
const handleLimitChange = (event) => {
setLimit(event.target.value);
};
const handlePageChange = (event, newPage) => {
setPage(newPage);
};
return (
<Card>
<PerfectScrollbar>
<Box sx={{ minWidth: 1050 }}>
<Table>
<TableHead>
<TableRow>
<TableCell>
Account
</TableCell>
<TableCell>
Name
</TableCell>
<TableCell>
Email
</TableCell>
<TableCell>
Location
</TableCell>
<TableCell>
Phone
</TableCell>
<TableCell>
Registration date
</TableCell>
<TableCell>
Action
</TableCell>
</TableRow>
</TableHead>
</Table>
</Box>
</PerfectScrollbar>
<TablePagination
component="div"
count={5}
onPageChange={handlePageChange}
onRowsPerPageChange={handleLimitChange}
page={page}
rowsPerPage={limit}
rowsPerPageOptions={[5, 10, 25]}
/>
</Card>
);
};
export default CustomerListResults;
CustomersList:
import { Helmet } from 'react-helmet';
import { Box, Container } from '#material-ui/core';
import CustomerListResults from '../components/customer/CustomerListResults';
import CustomerListToolbar from '../components/customer/CustomerListToolbar';
const CustomerList = () => (
<>
<Helmet>
<title>Customers | </title>
</Helmet>
<Box
sx={{
backgroundColor: 'background.default',
minHeight: '100%',
py: 3
}}
>
<Container maxWidth={false}>
<CustomerListToolbar />
<Box sx={{ pt: 3 }}>
<CustomerListResults />
</Box>
</Container>
</Box>
</>
);
export default CustomerList;
My Server API:
//API To Get All Users
app.get("api/fetchUsers", (req, res) => {
db.query("SELECT * FROM users", (req, res) => {
if (err){
console.log(err)
}else{
console.log(result);
res.send(result)
}
});
});
Change in below line, add / in start:
app.get("/api/fetchUsers", (req, res) => {})
I'm trying to bind to a nested array to text inputs from a form. There are 6 blocks and each block contains 3 values. I have initially populated the array for mapping by using:
new Array(6).fill(['','',''])
and rendering the values using 2 loops. One for the 6 blocks and the other 3 values inside each block. The 3 values are the ones binding to the form. I refer to each of the inputs using the second parameter of the map function which is the index.
Here is the code in its entirety.
import {
Card,
CardContent,
CardHeader,
CardMedia,
TextField,
Grid,
Typography,
Button,
} from "#material-ui/core";
import axios from "axios";
import { useState } from "react";
import { useHistory } from "react-router";
export default function CreateEditQuestion() {
const answerPack = new Array(6).fill(["", "", ""]);
const [question, setQuestion] = useState("");
const [answers, setAnswer] = useState(answerPack);
const [TimeAllowed, setTimeAllowed] = useState(30);
const [Score, setScore] = useState(1);
const [Date, setDate] = useState("");
const history = useHistory();
const handleAnswerSet = (value, answerIndex, answerTextIndex) => {
var updatedAnswer = answers;
updatedAnswer[answerIndex][answerTextIndex] = value;
setAnswer(updatedAnswer);
};
const handleSubmit = () => {
let data = {
question,
answer_set: answers,
time_allowed: TimeAllowed,
score_value: Score,
date: Date,
};
for (const [key, value] of Object.entries({ question, Date })) {
if (value.trim().length == 0) {
alert(`${key} has not been filled in`);
return false;
}
}
axios
.post(
"https://localhost:8000/question",
data
)
.then((resp) => {
alert("Succesfully added Question");
history.push("/question");
})
.catch((err) => {
console.log(err);
});
};
return (
<>
<h1>Create Question</h1>
<Card elevation={1}>
<CardHeader></CardHeader>
<CardContent>
<div>
<TextField
fullWidth
label="Question"
variant="outlined"
onChange={(e) => {
setQuestion(e.target.value);
}}
></TextField>
</div>
<Grid container direction={"row"} spacing={4}>
{answers.map((answerTexts, i) => {
return (
<Grid key={i} item md={4} width={50}>
{answerTexts.map((text, j) => {
return (
<div style={{ width: "70%", marginTop: "30px" }}>
<TextField
fullWidth
label={`Answer ${i + 1} - ${j + 1}`}
onChange={(ev) => {
handleAnswerSet(ev.target.value, i, j);
}}
variant="outlined"
/>
<br />
</div>
);
})}
</Grid>
);
})}
</Grid>
<Grid container direction={"row"} spacing={4}>
<Grid item md={5} width={80}>
<Typography variant="h6" gutterBottom gutterTop>
Extra Options
</Typography>
<TextField
label={"Time Allowed : "}
variant="outlined"
defaultValue={TimeAllowed}
onChange={(ev) => {
setTimeAllowed(ev.target.value);
}}
/>{" "}
<TextField
label="Score"
variant="outlined"
defaultValue={Score}
onChange={(ev) => {
setScore(ev.target.value);
}}
/>
</Grid>
<Grid item md={5} width={100}>
<Typography variant="h6" gutterBottom gutterTop>
Question Date
</Typography>
<TextField
type="date"
onChange={(ev) => {
setDate(ev.target.value);
}}
/>
</Grid>
</Grid>
<div align="center">
<Button
onClick={() => {
handleSubmit();
}}
variant="contained"
color="primary"
>
Submit Question
</Button>
</div>
</CardContent>
</Card>
</>
);
}
Problem:
On each block, changing any value also changes all the other corresponding inputs in other blocks, so if the first input on the first block is changed, then all other first inputs in the other blocks also get changed,e.g(changing answer 1-1 also changes 2-1,3-1,4-1, etc). I could not trace why. Only the corresponding values should be changed
This is the function responsible for setting the values.
const handleAnswerSet = (value, answerIndex, answerTextIndex) => {
var updatedAnswer = answers;
updatedAnswer[answerIndex][answerTextIndex] = value;
setAnswer(updatedAnswer);
};
Hello here is my problem, I have implemented a table that table fill when I choose some suggestion. The table contains three columns of (product, qty, balance and add button) So when I click add button it displays some popup form.
So I want to do when adding some quantity in the popup menu and after that click the add button it will reduce from the balance field in the table according to the selected product. Below is the table array.
import React, { useState } from "react"
import {
Grid,
Table,
TableContainer,
TableHead,
TableRow,
TableCell,
Paper,
TableBody,
Button
} from "#material-ui/core"
import AddItem from "./AddItem"
import { useStyles } from "../../../../styles/classes"
export default function ItemsList({
cart,
handleChange,
handleBlur,
values,
setFieldValue,
volumes
}) {
const [open, setOpen] = useState(false)
const [productId, setProductId] = useState("")
const [factoryId, setFactoryId] = useState("")
const handleClickOpen = (productId, factoryId) => {
setProductId(productId)
setFactoryId(factoryId)
setOpen(true)
}
const handleClose = (value) => {
setOpen(false)
}
const addToList = (factory) => {
setOpen(false)
const product = cart.find(
(item) => item.productId === Number(productId)
)
const item = {
productId: productId,
productName: product.productName,
containerNo: values.containerNo,
sealNo: values.sealNo,
qty: values.qty,
factoryId: factory.id,
factory: factory.name,
printDate: values.printDate,
printTime: values.printTime,
palletNo: values.palletNo,
}
const idx = values.volumes.findIndex(e=>e.number === Number(values.noOfContainers))
console.log(idx)
const current = values.volumes[idx].data;
current.push(item)
setFieldValue(`volumes[${idx}].data`,current)
//sum of qty in loaded volumes for this product
values.invoiceItems.forEach((item, idx) => {
item.balance = (Number(item.balance) - Number(values.qty))
})
setFieldValue('invoiceItems', values.invoiceItems)
}
const classes = useStyles()
return (
<Grid item md={12} sm={12} xs={12}>
<TableContainer component={Paper} >
<Table className={classes.table} size="small">
<TableHead>
<TableRow>
<TableCell align="left">Product</TableCell>
<TableCell align="left">Quantity</TableCell>
<TableCell align="left">Balance</TableCell>
<TableCell align="left">Add</TableCell>
</TableRow>
</TableHead>
<TableBody>
{cart.map((row, i) => (
<TableRow key={i}>
<TableCell align="left">{row.productName}</TableCell>
<TableCell align="left">{row.qty}</TableCell>
<TableCell align="left">{row.balance}</TableCell>
<TableCell align="left">
<Button
variant="outlined"
size="small"
color="secondary"
onClick={() => {
handleClickOpen(row.productId)
}}>
add
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<AddItem
open={open}
onClose={handleClose}
handleChange={handleChange}
handleBlur={handleBlur}
values={values}
addToList={addToList}
volumes={volumes}
/>
</Grid>
)
}
import React, { useState} from "react"
import {
Grid,
Card,
CardContent,
CardActions,
Button,
CardHeader,
} from "#material-ui/core"
import Alert from "#material-ui/lab/Alert"
import axios from 'axios'
//validation
import { Formik, Form } from "formik"
import * as Yup from 'yup'
import { useStyles } from "../../../styles/classes"
import ItemList from "./subComponents/ItemsList"
import MetaData from "./subComponents/MetaData"
import ContainerList from "./subComponents/ContainerList"
import {useInitialValues} from '../../../hooks/useLoadingInfoData'
// validation schema
let validationSchema = Yup.object().shape({
volumes: Yup.string().required(),
})
export default function LoadingInfo(props) {
const classes = useStyles()
const [initialValues, setInitialValues] = useInitialValues()
const [volumes, setVolumes] = useState([])
const [alert, setAlert] = useState({
showAlert: false,
severity: "success",
message: "",
})
// create method
const submit = async (e, { resetForm }) => {
try {
await axios.post("/loadingInfo", e)
resetForm()
setAlert({
showAlert: true,
severity: "success",
message: "Loading Information created successfully!",
})
} catch (error){
if (error.response.status === 422) {
setAlert({
showAlert: true,
severity: 'error',
message: 'Loading information already exists!',
})
} else {
setAlert({
showAlert: true,
severity: 'error',
message: 'Loading information creation failed!',
})
}
}
}
return (
<Grid container className={classes.root} spacing={1}>
<Grid item xs={12} sm={12} md={12}>
<Formik
initialValues={initialValues}
onSubmit={submit}
validationSchema={validationSchema}
enableReinitialize>
{({
isValid,
dirty,
values,
handleChange,
handleBlur,
setFieldValue,
errors,
}) => {
return (
<Form>
<Card variant="outlined" style={{marginBottom: '1rem'}}>
<CardHeader title="Loading Information"></CardHeader>
<CardContent>
<Grid container spacing={1}>
<MetaData
values={values}
handleChange={handleChange}
handleBlur={handleBlur}
setAlert={setAlert}
setFieldValue={setFieldValue}
/>
<ItemList
cart={values.invoiceItems}
values={values}
handleChange={handleChange}
handleBlur={handleBlur}
setFieldValue={setFieldValue}
volumes={volumes}
/>
</Grid>
</CardContent>
</Card>
<Card variant="outlined">
<CardContent>
{values.volumes.map( (data , idx) =>
<ContainerList values={data} idx={idx} setFieldValue={setFieldValue}/>
)}
</CardContent>
<CardActions>
<Button
variant="contained"
color="primary"
type="submit"
disabled={!dirty || !isValid}>
create
</Button>
</CardActions>
</Card>
</Form>
)
}}
</Formik>
</Grid>
<Grid></Grid>
{alert.showAlert && (
<Grid item md={12}>
<Alert
severity={alert.severity}
onClose={() =>
setAlert({
...alert,
showAlert: false,
})
}>
{alert.message}
</Alert>
</Grid>
)}
</Grid>
)
}