I am trying to create a download link in a React front end where the user will be clicking a button and a file will be downloaded.
To acheive this, I am trying to pass the file path inside a JS function and inside the function I want to call an API endpoint with that path, and the api will return me the file.
Now, for some reason, the code I am writing is not working. Kindly help me to rectify my mistake.
import React, { useState, useEffect } from "react";
import axios from "axios";
import moment from "moment";
import {
Grid,
Paper,
Typography,
Table,
TableCell,
TableContainer,
TableHead,
TableRow,
TableBody,
} from "#mui/material";
import Download from './Download';
import FileDownload from "js-file-download";
export default function Classroomtest() {
const uid = localStorage.getItem("uniqueid");
const [assignments, setassignments] = useState("");
useEffect(() => {
axios
.get(`http://localhost:5000/api/v1/app/get-my-assignments/${uid}`)
.then((res) => {
setassignments(res.data);
});
}, []);
const view = (path) =>{
//Nothing is coming here
}
return (
<Grid>
<Paper
sx={{
padding: 3,
margin: 1,
}}
>
<TableContainer
component={Paper}
sx={{
margin: "10px",
width: "97%",
}}
>
<Table sx={{ minWidth: 100 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell align="right">Topic</TableCell>
<TableCell align="right">Due</TableCell>
<TableCell align="right">Action</TableCell>
<TableCell align="right">Delete</TableCell>
</TableRow>
</TableHead>
{assignments?.data?.myassignments.map((item) => (
<TableBody key={item._id}>
<TableCell align="right">{item.assignmentname}</TableCell>
<TableCell align="right">{moment.utc(item.duedate).format("MMMM,DD")}</TableCell>
<TableCell align="right">
<button type="button" onClick={view(item.assignmentfilepath)}>Download</button>
</TableCell>
<TableCell align="right">Java</TableCell>
</TableBody>
))}
</Table>
</TableContainer>
</Paper>
</Grid>
);
}
Example of a file path returned is : uploads\user-1638470921415.pdf
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 want to update the text of a button when i click on that button. I am using setState for that but i am unable to use it as it gives me the following error:
TypeError: Cannot read properties of undefined (reading 'state')
Here is my code:
import Head from 'next/head';
import { Box, Container, Grid, Pagination } from '#mui/material';
import { products } from '../__mocks__/products';
import { ProductListToolbar } from '../components/product/product-list-toolbar';
import { ProductCard } from '../components/product/product-card';
import { DashboardLayout } from '../components/dashboard-layout';
import { CustomerListResults } from '../components/trip/trip-list-results';
import { customers } from '../__mocks__/customers';
import { trips } from '../__mocks__/trips';
import { TripListResults } from '../components/customer/customer-list-results';
import {
Avatar,
Card,
Checkbox,
Table,
TableBody,
TableCell,
TableHead,
TablePagination,
TableRow,
Typography,
Button
} from '#mui/material';
import NextLink from 'next/link';
const TripRequests = () => {
const accept =()=> {
this.setState({accept: 'Payment Pending'})
console.log("fsfdsa");
};
this.state = {
accept: "Accept"
};
return (
<>
<Head>
<title>
Trip Requests
</title>
</Head>
<Box
component="main"
sx={{
flexGrow: 1,
py: 8
}}
>
<Container maxWidth={false}>
<Box sx={{ mt: 3 }}>
{/* <CustomerListResults customers={trips} /> */}
<h2>Trip Requests (2)</h2>
</Box>
<Box sx={{ minWidth: 1050, mt: 3 }}>
<Table>
<TableHead>
<TableRow>
<TableCell padding="checkbox">
{/* <Checkbox
// checked={selectedCustomerIds.length === customers.length}
color="primary"
// indeterminate={
// selectedCustomerIds.length > 0
// && selectedCustomerIds.length < customers.length
// }
// onChange={handleSelectAll}
/> */}
</TableCell>
{/* <TableCell>
Trip Id
</TableCell> */}
<TableCell>
Customer
</TableCell>
<TableCell>
Departure
</TableCell>
<TableCell>
Destination
</TableCell>
<TableCell>
Truck / Driver
</TableCell>
<TableCell>
Action
</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow
hover
// key={customer.id}
// selected={selectedCustomerIds.indexOf(customer.id) !== -1}
>
<TableCell padding="checkbox">
{/* <Checkbox
checked={selectedCustomerIds.indexOf(customer.id) !== -1}
onChange={(event) => handleSelectOne(event, customer.id)}
value="true"
/> */}
</TableCell>
<TableCell>
Rohan Joshi
</TableCell>
<TableCell>
<Box
sx={{
alignItems: 'center',
display: 'flex'
}}
>
{/* <Avatar
src={customer.avatarUrl}
sx={{ mr: 2 }}
>
{getInitials(customer.name)}
</Avatar> */}
<Typography
color="textPrimary"
variant="body1"
>
A-50, Sec 67, Noida
</Typography>
</Box>
</TableCell>
<TableCell>
HUDA City Center
</TableCell>
<TableCell>
fds
</TableCell>
<TableCell>
<Button onClick={accept}>{state.accept}</Button>
<Button>Decline</Button>
</TableCell>
{/* <TableCell>
{format(customer.createdAt, 'dd/MM/yyyy')}
</TableCell> */}
</TableRow>
</TableBody>
</Table>
</Box>
</Container>
</Box>
</>
);
TripRequests.getLayout = (page) => (
<DashboardLayout>
{page}
</DashboardLayout>
)};
export default TripRequests;
Looks like you are mixing class-based components with function components. In your case this refers to the module-level this which is undefined. Function components don't make use of this.
To use state in function components you need to use the useState hook:
const TripRequests = () => {
const [acceptState, setAcceptState] = useState('Accept')
const accept = () => setAcceptState('Payment Pending')
// ...
}
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) => {})
Alright, it took me awhile to even formulate the question for this. This is more related to a design strategy rather than anything.
I have a view that contains a table that displays a list of all users.Each row of the table has an icon on the left that will expand (or collapse) a component called UsersTrainingSummary that just brings a summary of some specific data. See image:
Here is the full code of this view component:
import React from 'react';
import { Card, CardContent, CardHeader, Chip, Divider, Grid, Typography } from '#material-ui/core';
import { gridSpacing } from '../../../store/constant';
import TableContainer from '#material-ui/core/TableContainer';
import Table from '#material-ui/core/Table';
import TableHead from '#material-ui/core/TableHead';
import TableRow from '#material-ui/core/TableRow';
import MuiTableCell from '#material-ui/core/TableCell';
import TableBody from '#material-ui/core/TableBody';
import { makeStyles, withStyles } from '#material-ui/core/styles';
import {Link} from "react-router-dom";
import IconButton from '#material-ui/core/IconButton';
import KeyboardArrowDownIcon from '#material-ui/icons/KeyboardArrowDown';
import KeyboardArrowUpIcon from '#material-ui/icons/KeyboardArrowUp';
import moment from 'moment';
import UsersTrainingSummary from './UsersTrainningSummary';
import useLocalStorage from 'react-use-localstorage';
import { useQuery } from '#apollo/client';
import ALL_USERS from '../../../graphql/AllUsers';
import Loader from '../../../component/Loader/Loader';
const useStyles = makeStyles({
table: {
minWidth: 350,
},
});
const TableCell = withStyles({
root: {
borderBottom: "none"
}
})(MuiTableCell);
function createData(userId, username, firstName, lastName, dateJoined, lastLogin, email, isActive, trainings ) {
return { userId, username, firstName, lastName, dateJoined, lastLogin, email,isActive, trainings };
}
const UserDashboard = () => {
const classes = useStyles();
const [storage, setStorage] = useLocalStorage('orgId');
const orgId = storage
const { data, error , loading} = useQuery(ALL_USERS, {
variables: {
orgId: Number(orgId)
},
});
function Row(props){
const { row } = props;
const [open, setOpen] = React.useState(false);
return (
<React.Fragment>
<TableRow key={row.userId}>
<TableCell>
<IconButton aria-label="expand row" size="small" onClick={() => setOpen(!open)}>
{open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</IconButton>
</TableCell>
<Link to={{pathname: `/users/${row?.userId}`, state: { user: row}}}
style={{ textDecoration: 'none' }}>
<TableCell
className={classes.root} hover={true}
component="th" scope="row">{row?.username}
</TableCell>
</Link>
<TableCell>{row.firstName}</TableCell>
<TableCell>{row.lastName}</TableCell>
<TableCell>{moment(row?.dateJoined).format('MM/DD/YYYY')}</TableCell>
<TableCell>{moment(row?.lastLogin).format('MM/DD/YYYY')}</TableCell>
<TableCell>{row?.email}</TableCell>
<TableCell>{row?.isActive? <React.Fragment>Yes</React.Fragment> : <React.Fragment>No</React.Fragment>}</TableCell>
</TableRow>
<TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
{open && <UsersTrainingSummary userId={row.userId} trainings={row.trainings}/>}
</TableCell>
</TableRow>
</React.Fragment>
)
}
if(data) {
let userList = data.organization?.user
const rows = [];
if (userList) {
userList.map((user) => {
rows.push(createData(user.id, user.username, user.firstName, user.lastName, user.dateJoined, user.lastLogin,
user.email, user.isActive, user.trainings))
})
}
return (
<Grid container spacing={gridSpacing}>
<Grid item xs={12}>
<Card>
<CardHeader
title={
<Typography component="div" className="card-header">
List of all trainees
</Typography>
}
/>
<Divider/>
<CardContent className="p-0">
<TableContainer>
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell></TableCell>
<TableCell>Username</TableCell>
<TableCell>First Name</TableCell>
<TableCell>Last Name</TableCell>
<TableCell>Date Joined</TableCell>
<TableCell>Last Login</TableCell>
<TableCell>Email</TableCell>
<TableCell>Is Active</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows?.length > 0 && rows.map((row) => (
<Row key={row?.userId} row={row}/>
))}
</TableBody>
</Table>
</TableContainer>
</CardContent>
</Card>
</Grid>
</Grid>
);
}
else
return ( <Loader />)
}
export default UserDashboard
Because the query that brings the summary data can be quite slow if you try to bring for too many users at once due to the involved tables in the DB having a huge amount of data, and because most of the time you will only need for one or a few users, I decided to use a lazy strategy: only when the user clicks on that arrow icon, the component UsersTrainingSummary is rendered and there I have the graphql query that brings the data from the backend and
also do all the necessary logic to render that Collapse component.
What I am trying to achieve now is to only display that icon for users that actually have something to show e.g query does not bring empty results from BE, because as user it feels a little misleading to me to have that icon just so you can click and see a message "oh...nothing here". However, since I need to execute the query first in order to know if there's something to display, it doesn't seem possible to me unless I perform that query first for all users, which is something I really don't wanna do, as the weight on performance is much bigger than the weight on user friendly interface.
Or, is there a way I can achieve this?
As mentioned in the comment, an alternative to querying the DB in order to find all users who have additional information, could be managing the issue on back-end side, by adding a boolean field (e.g. "hasMoreInfo") to the table that you use to populate the first view and use that value to decide whether to render or not the icon.
I have added a react mat ui table to my app and added switches into one of the columns but for some reason they all toggle together rather than independently.
How can I change this?
<TableBody>
{operators.map((row) => (
<TableRow key={row.key}>
<TableCell component="th" scope="row">
{row.operator}
</TableCell>
<TableCell>
<Typography component="div">
<Grid
component="label"
container
alignItems="center"
// justify="flex-end"
spacing={1}
>
<Grid item>Off</Grid>
<Grid item>
<AntSwitch
checked={checkboxState.checkedC}
onChange={handleChange}
name="checkedC"
/>
</Grid>
<Grid item>On</Grid>
</Grid>
</Typography>
</TableCell>
<TableCell align="right">{'<<Placement value>>'}</TableCell>
</TableRow>
))}
</TableBody>
I just created a demo in a sandbox to show you but the strange thing is that it works correctly there but not in my app.
The full code is in my Gist: https://gist.github.com/SerdarMustafa1/b3214b01885980e433405987f8822fe7
and demo: https://stackblitz.com/edit/5dm8lk?file=demo.js.
Any ideas what's gone wrong?
You can use array of states to keep the state of each raw:
import React, {useState} from "react";
import { withStyles } from "#material-ui/core/styles";
import { purple } from "#material-ui/core/colors";
import FormGroup from "#material-ui/core/FormGroup";
import FormControlLabel from "#material-ui/core/FormControlLabel";
import Switch from "#material-ui/core/Switch";
import Grid from "#material-ui/core/Grid";
import Table from "#material-ui/core/Table";
import TableBody from "#material-ui/core/TableBody";
import TableCell from "#material-ui/core/TableCell";
import TableContainer from "#material-ui/core/TableContainer";
import Typography from '#material-ui/core/Typography';
import TableHead from "#material-ui/core/TableHead";
import TableRow from "#material-ui/core/TableRow";
import Paper from "#material-ui/core/Paper";
import { makeStyles, withStyles } from "#material-ui/core/styles";
const AntSwitch = withStyles(theme => ({
root: {
width: 28,
height: 16,
padding: 0,
display: "flex"
},
switchBase: {
padding: 2,
color: theme.palette.grey[500],
"&$checked": {
transform: "translateX(12px)",
color: theme.palette.common.white,
"& + $track": {
opacity: 1,
backgroundColor: theme.palette.primary.main,
borderColor: theme.palette.primary.main
}
}
},
thumb: {
width: 12,
height: 12,
boxShadow: "none"
},
track: {
border: `1px solid ${theme.palette.grey[500]}`,
borderRadius: 16 / 2,
opacity: 1,
backgroundColor: theme.palette.common.white
},
checked: {}
}))(Switch);
const tableStyles = makeStyles({
table: {
minWidth: 150
}
});
export default function CustomizedSwitches() {
const [gridData, setGridData] = useState([
{ key: 6, operator: "OyPohjolanLiikenne Ab", checked: false },
{ key: 12, operator: "Helsingin Bussiliikenne Oy", checked: true },
{ key: 17, operator: "Tammelundin Liikenne Oy", checked: false },
{ key: 18, operator: "Pohjolan Kaupunkiliikenne Oy", checked: true },
{ key: 20, operator: "Bus Travel Åbergin Linja Oy", checked: false },
{ key: 21, operator: "Bus Travel Oy Reissu Ruoti", checked: true }
]);
const handleChange = (event, index) => {
gridData[index].checked = event.target.checked;
setGridData([...gridData]);
};
const tableClasses = tableStyles();
return (
<TableContainer component={Paper}>
<Table
stickyHeader
className={tableClasses.table}
size="small"
aria-label="a dense table"
>
<TableHead>
<TableRow>
<TableCell>Operator</TableCell>
{/* <TableCell align="right">Listed</TableCell> */}
<TableCell>Visible</TableCell>
<TableCell align="right">Total Placements</TableCell>
</TableRow>
</TableHead>
<TableBody>
{gridData.map( (row, index) => (
<TableRow key={row.key}>
<TableCell component="th" scope="row">
{row.operator}
</TableCell>
<TableCell>
<Typography component="div">
<Grid
component="label"
container
alignItems="center"
// justify="flex-end"
spacing={1}
>
<Grid item>Off</Grid>
<Grid item>
<AntSwitch
checked={row.checked}
onChange={(event) => handleChange(event, index)}
name="checkedC"
/>
</Grid>
<Grid item>On</Grid>
</Grid>
</Typography>
</TableCell>
<TableCell align="right">{"<<Placement value>>"}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
Combining Arthur Ruben's answer and Drew Reese's comment.
Here's how I assigned props to a switch state array to be used by the switch and update fields inside the grid depending on the state of that switch.
Each row inside table needs its own state (and each column, as well, if you want to change columns within rows). You can monitor state of different switches as well as change fileds inside the row this way.
export default function TableComponent(props) {
const { rows } = props;
// generate array from incoming props,
// to be assigned to the state of this components
let stateInitArray = rows.map((row, index) => ({
id: index,
checked: false,
transactionType: "Session",
}));
const [gridState, setGridState] = React.useState(stateInitArray);
const handleSwitchChange = (event, index) => {
const { checked } = event.target;
let transactionType = checked ? "Payment" : "Session";
setGridState((prevState) =>
prevState.map((row, i) =>
// iterate over the state and update value of row where the switch was pressed
i === index ? { ...row, checked, transactionType } : row
)
);
};
return (
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} size="small" aria-label="a dense table">
<TableHead>
<TableRow>
<TableCell align="left">isPayment?</TableCell>
<TableCell>Date</TableCell>
<TableCell align="left">Cost</TableCell>
<TableCell align="left">Transaction Type</TableCell>
<TableCell align="left">Column Gap</TableCell>
<TableCell align="left">Column Gap</TableCell>
<TableCell align="left">Column Gap</TableCell>
<TableCell align="left">Message</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map((row, index) => (
<TableRow
key={row.name}
sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
>
<TableCell>
<Switch
key={gridState[index].id}
checked={gridState[index].checked}
onChange={(event) => {
handleSwitchChange(event, index);
}}
inputProps={{ "aria-label": "controlled" }}
/>
</TableCell>
<TableCell component="th" scope="row">
{row.date}
</TableCell>
<TableCell align="left">
{gridState[index].transactionType === "Payment" ? "" : row.cost}
</TableCell>
<TableCell align="left">
{gridState[index].transactionType}
</TableCell>
<TableCell align="left"></TableCell>
<TableCell align="left"></TableCell>
<TableCell align="left"></TableCell>
<TableCell align="left">{row.message}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}