I'm from Angular and new to React. Im doing well but here is a problem I'm stuck at. As you can see I have BasicLayout and AppointmentForm, both are in one file. BasicLayout is being used inside AppointmentForm but not like an element i.e <BasicLayout/> so I'm not able to understand how to pass props or its even possible now. I want to trigger commitChanges(inside AppointmentForm) function when onSubmit(inside Basic Layout) function is triggered. How can I pass props between these components?
const BasicLayout = (props) => {
const formik = useFormik({
initialValues: {
title: '',
agenda: '',
description: '',
participants: [],
host: user?.id,
guest: '',
location: '',
},
validationSchema,
onSubmit: async (values) => {
values.startDate = props.appointmentData.startDate;
values.endDate = props.appointmentData.endDate;
values.guest = values.guest?._id;
createAppointment(values);
console.log(values);
},
});
return (
<Container>
<Typography sx={{ fontSize: 24, fontWeight: 'bold' }} color="text.primary" gutterBottom>
Create Appointment
</Typography>
<Box sx={{ flexGrow: 1 }}>
<FormikProvider value={formik}>
<Form autoComplete="off" onSubmit={handleSubmit}>
<Grid container spacing={2}>
<Grid item xs={6} md={6}>
<TextField
label="Title"
color="secondary"
id="title"
type="text"
key="title"
value={formik.values.title}
onChange={formik.handleChange}
{...getFieldProps('title')}
error={Boolean(touched.title && errors.title)}
helperText={touched.title && errors.title}
fullWidth
/>
</Grid>
<Grid item container xs={12} md={12} direction="row" justifyContent="center" alignItems="center">
<LoadingButton size="medium" type="submit" variant="contained" loading={isSubmitting}>
Create
</LoadingButton>
</Grid>
</Grid>
</Form>
</FormikProvider>
</Box>
<ToastContainer />
</Container>
);
};
const AppointmentsDashboard = (props) => {
const commitChanges = ({ added, changed, deleted }) => {
console.log(props);
console.log({ added, changed, deleted });
if (added) {
if (!isValidate) {
notify('Please fill all required fields', 'error');
return;
}
const startingAddedId = data.length > 0 ? data[data.length - 1].id + 1 : 0;
setData([...data, { id: startingAddedId, ...added }]);
}
if (changed) {
setData(
data.map((appointment) =>
changed[appointment.id] ? { ...appointment, ...changed[appointment.id] } : appointment
)
);
}
if (deleted !== undefined) {
setData(data.filter((appointment) => appointment.id !== deleted));
}
return data;
};
return (
<>
<Paper>
<Scheduler data={data} height={660}>
<ViewState currentDate={currentDate} />
<EditingState
onCommitChanges={commitChanges}
addedAppointment={addedAppointment}
onAddedAppointmentChange={changeAddedAppointment}
appointmentChanges={appointmentChanges}
onAppointmentChangesChange={changeAppointmentChanges}
editingAppointment={editingAppointment}
onEditingAppointmentChange={changeEditingAppointment}
onAppointmentFormClosing={() => {
console.log('asdasd');
}}
allowAdding={true}
/>
<WeekView startDayHour={9} endDayHour={17} />
<AllDayPanel />
<EditRecurrenceMenu />
<ConfirmationDialog />
<Appointments />
<AppointmentTooltip showOpenButton showDeleteButton />
<AppointmentForm basicLayoutComponent={BasicLayout} />
</Scheduler>
</Paper>
</>
);
};
export default AppointmentsDashboard;
Related
I want to share state between two routes when I click on the link for one of the routes (NewUser). The state that I want to share and the logic modifying it are both held in the Users route. I want to pass the logic to change the state to the NewUsers route.
When I pass a string to the state object in router Link, I am able to access it in the NewUsers component. However, I get null when I pass a function.
I know that I can use context/redux, but I would prefer if I can do it this way.
Users route:
function Users() {
const [users, setUsers] = useState([]);
return (
<Card sx={{ padding: "2rem", mt: "2rem" }}>
<MDBox
display="flex"
flexDirection="row"
justifyContent="space-between"
>
<MDTypography variant="body2">{`You currently have ${users.length} users`}</MDTypography>
<MDButton variant="gradient" color="info" size="small">
<Link to="/settings/users/new-user" state={setUsers: setUsers}> //this is how I want to pass the state
<MDBox
display="flex"
alignItems="center"
color="white"
fontWeight="normal"
>
<Icon>add</Icon> Add New User
</MDBox>
</Link>
</MDButton>
</MDBox>
</Card>
NewUsers route:
function NewUser({history}) {
const location = useLocation();
const saveChanges = (e) => {
location.state.setUsers({
fname: values.firstName,
lname: values.lname,
email: values.email,
});
navigate("/settings/users");
};
return(
<MDBox py={3} mb={20} height="62vh">
<Grid
container
justifyContent="center"
alignItems="center"
sx={{ height: "100%", mt: 0 }}
>
<Grid item xs={12} lg={12}>
<Formik
initialValues={initialValues}
validationSchema={currentValidation}
onSubmit={(values) => {
setValues(values);
}}
>
{({ values, errors, touched, isSubmitting }) => (
<Form id={formId} autoComplete="off">
<Card sx={{ height: "100%", width: "100%" }}>
<MDBox px={3} py={4}>
<MDBox display="flex">
<ButtonWrapper
fullWidth={false}
handleClick={saveChanges}
>
Save Changes
</ButtonWrapper>
</MDBox>
<MDBox>
{getStepsContent({
values,
touched,
formField,
errors,
})}
</MDBox>
</MDBox>
</Card>
</Form>
)}
</Formik>
</Grid>
</Grid>
</MDBox>
)
}
Routing code:
{
type: "collapse",
name: "Settings",
key: "settings",
icon: <Icon fontSize="small">settings</Icon>,
collapse: [
{
name: "Users",
key: "users",
route: "/settings/users",
// icon: <Icon fontSize="small">users</Icon>,
component: <Users />,
},
{
name: "Companies",
key: "companies",
route: "/settings/companies",
component: <Companies />,
},
{
name: "Billing",
key: "billing",
route: "/settings/billing",
component: <Billing />,
},
{
name: "Integrations",
key: "integrations",
route: "/settings/integrations",
component: <Integrations />,
},
],
},
{
name: "New User",
key: "new user",
route: "/settings/users/new-user",
noCollapse: true,
component: <NewUser />,
},
{
type: "collapse",
name: "Sign Out",
key: "signout",
route: "/sign-out",
icon: <Icon fontSize="small">logout</Icon>,
component: <SignOut />,
noCollapse: true,
},
];
function that renders the routes:
const getRoutes = (allRoutes) =>
allRoutes.map((route) => {
if (route.collapse) {
return getRoutes(route.collapse);
}
if (route.route) {
return <Route exact path={route.route} element={route.component} key={route.key} />;
}
return null;
});
<Routes>
{getRoutes(routes)}
{/* <Route path="*" element={<Navigate to="/dashboard" />} /> */}
<Route path="*" element={<Console />} />
</Routes>
The state value sent via the Link component needs to be JSON serializable. Javascript functions are not serializable. Instead of trying to pass a function through to a target component I recommend lifting the state up to a common ancestor so the state and callback function is accessible to both components.
I would suggest using a React context to hold the users state and provide out the state value and an updater function to add a user object. react-router-dom has a "built-in" way to do this via a layout route component that renders an Outlet component that wraps nested routes.
Example:
import { Outlet } from 'react-router-dom';
const UsersProvider = () => {
const [users, setUsers] = useState([]);
const addUser = (user) => {
setUsers((users) => users.concat(user));
};
return <Outlet context={{ users, addUser }} />;
};
...
<Routes>
...
<Route path="/settings/users" element={<UsersProvider />}>
<Route index element={<Users />} />
<Route path="new-user" element={<NewUser />} />
</Route>
...
</Routes>
Users
const Users = () => {
const { users } = useOutletContext();
return (
<Card sx={{ padding: "2rem", mt: "2rem" }}>
<Box display="flex" flexDirection="row" justifyContent="space-between">
<Typography variant="body2">
You currently have {users.length} users
</Typography>
<Button variant="gradient" color="info" size="small">
<Link to="/settings/users/new-user">
<Box
display="flex"
alignItems="center"
color="white"
fontWeight="normal"
>
<Icon>add</Icon>
Add New User
</Box>
</Link>
</Button>
</Box>
</Card>
);
};
NewUser
function NewUser({history}) {
const navigate = useNavigate();
const { addUser } = useOutletContext();
const saveChanges = (e) => {
addUser({
fname: values.firstName,
lname: values.lname,
email: values.email,
});
navigate("/settings/users");
};
return(
<MDBox py={3} mb={20} height="62vh">
<Grid
container
justifyContent="center"
alignItems="center"
sx={{ height: "100%", mt: 0 }}
>
<Grid item xs={12} lg={12}>
<Formik
initialValues={initialValues}
validationSchema={currentValidation}
onSubmit={(values) => {
setValues(values);
}}
>
{({ values, errors, touched, isSubmitting }) => (
<Form id={formId} autoComplete="off">
<Card sx={{ height: "100%", width: "100%" }}>
<MDBox px={3} py={4}>
<MDBox display="flex">
<ButtonWrapper
fullWidth={false}
handleClick={saveChanges}
>
Save Changes
</ButtonWrapper>
</MDBox>
<MDBox>
{getStepsContent({
values,
touched,
formField,
errors,
})}
</MDBox>
</MDBox>
</Card>
</Form>
)}
</Formik>
</Grid>
</Grid>
</MDBox>
)
}
I'm displaying US region incidents from Google Cloud API, but the problem is that it displays also repeated data, example:enter image description here
How can I remove the repeated ones? Here's the code.
DATA RETRIEVING:
export const getGoogleStatus = async () => {
const response = await axios.get('https://status.cloud.google.com/incidents.json')
console.log('Raw Data: ', response.data)
const status = response.data.map((e) => {
return {
name: e.affected_products.map((e) => {
return e.title
}),
status: e.most_recent_update.status,
location: e.most_recent_update.affected_locations.map((e) => {
return e.title
}).filter((r) => r.includes("(us-"))
}
})
return status
}
DATA DISPLAYING IN FRONTEND:
export default function GoogleStatusSummary({ listStatus }) {
if (!listStatus) return <div>Loading...</div>
return (
<Grid container padding={2} justifyContent='center'>
<Grid item padding={2}>
<Typography variant='h1' marginLeft={5}>
<TwitterIcon sx={{ mr: 2, mt: 1 }} />
Google API Status
</Typography>
{listStatus.map((item, index) => {
const { name, status, location } = item
const colorStatus = status === 'AVAILABLE' ? 'success' : 'danger'
return (
location.length > 0 && (
<Grid display='flex' m={3} key={index}>
<RadioButtonCheckedIcon sx={{ ml: 2, mt: 1 }} color={colorStatus} />
<Grid ml={2}>
<Typography variant='h4'>
{name}
</Typography>
<Typography variant='h6' style={{ fontSize: 12 }}>
{status.charAt(0).toUpperCase() + status.slice(1)}
</Typography>
</Grid>
</Grid>
)
)
})
}
</Grid>
</Grid>
)
export const data = [
{
size: "S",
colorMap: { Yellow: 10, Green: 5, Black: 50 },
productName: "Shirt",
price: 200
}
];
I wanted to show the initial values of the colorMapand then update its quantity. How can I update the quantities of the colors which are the values of the Object.entries(colorMap)?
Codesandbox: https://codesandbox.io/s/form-changehanlder-2-2repsp?file=/part2.js
The product here came from the parent component:
This is the child component
import React, { useState } from "react";
import { Grid, TextField } from "#mui/material";
const Part2 = ({ product }) => {
const [qty, setQty] = useState();
const handleSubmit = (e) => {
e.preventDefault();
console.log(qty);
};
return (
<div>
{product &&
product.map((prod, index) => (
<>
<Grid item key={index}>
<form onSubmit={handleSubmit}>
{Object.entries(prod.colorMap).map((color, index) => (
<Grid
container
rowSpacing={1}
columnSpacing={{ xs: 1, sm: 2, md: 3 }}
key={color[0]}
>
<Grid item xs={6}>
<TextField
type="text"
variant="outlined"
label="Color"
fullWidth
value={color[0]}
disabled
/>
</Grid>
<Grid item xs={6}>
<TextField
type="number"
variant="outlined"
fullWidth
label="Quantity"
value={color[1]}
onChange={(e) => console.log(index)}
/>
</Grid>
</Grid>
))}
</form>
</Grid>
</>
))}
</div>
);
};
export default Part2;
First make changeHandler in demo.js as you are using React State in demo.js so you have to make onChangeHandler in that file and pass it in props of part2.
Like:
const onChangeValues = (propertyName, index, value) => {
let item = product?.[index];
if (item) {
item.colorMap[propertyName] = value;
let prods = [...product];
prods[index] = item;
setProduct(prods);
}
};
And pass this function in props of Part2:
<Grid item>
<Part2 product={product} onChange={onChangeValues} />
</Grid>
In part2 Component you can consume it as follows:
<TextField
type="number"
variant="outlined"
fullWidth
label="Quantity"
value={color[1]}
onChange={({ target: { value } }) => {
onChangeHandler(color[0], index, value);
}}
/>
Codesandbox Link: https://codesandbox.io/s/form-changehanlder-2-forked-l9unl0?file=/part2.js:1131-1521
I am making an add sales component that requires an add button to add multiple products. I made it working with normal TextField with following code but when added Autocomplete, I am unable. Looking for help.
import React, { useState } from "react";
import {
Box,
TextField,
Grid,
InputLabel,
Tooltip,
IconButton,
Autocomplete
} from "#mui/material";
import { Add, Remove } from "#mui/icons-material";
const products = [
{ id: 1, name: "Green Apple" },
{ id: 2, name: "Red Cherry" },
{ id: 3, name: "Strawberry" },
{ id: 4, name: "Ground Apple" },
{ id: 5, name: "Dragon Fruit" },
{ id: 6, name: "White pear" }
];
function AddSale() {
const [inputList, setInputList] = useState([{ name: "", qty: "", rate: "" }]);
// handle input change
const handleInputChange = (e, index) => {
const { name, value } = e.target;
const list = [...inputList];
list[index][name] = value;
setInputList(list);
};
// handle click event of the Remove button
const handleRemoveClick = (index) => {
const list = [...inputList];
list.splice(index, 1);
setInputList(list);
};
// handle click event of the Add button
const handleAddClick = () => {
setInputList([...inputList, { name: "", qty: "", rate: "" }]);
};
return (
<Grid container spacing={2}>
<Grid item sx={{ py: 0 }} xs={5}>
<InputLabel>Select a item*</InputLabel>
</Grid>
<Grid item sx={{ py: 0 }} xs={2}>
<InputLabel>Qty (Piece)*</InputLabel>
</Grid>
<Grid item sx={{ py: 0 }} xs={3}>
<InputLabel>Rate (Rs)*</InputLabel>
</Grid>
<Grid item sx={{ py: 0 }} xs={2} />
{inputList.map((x, i) => {
return (
<React.Fragment key={i}>
<Grid item xs={5}>
<Autocomplete
value={x.name}
onChange={(e) => handleInputChange(e, i)}
inputValue={x.name}
onInputChange={(e) => handleInputChange(e, i)}
id="select-product"
options={products}
disableClearable
getOptionLabel={(option) => option.name}
renderOption={(props, option) => (
<li {...props}>{option.name}</li>
)}
renderInput={(params) => (
<TextField
name="name"
{...params}
placeholder="Select product"
/>
)}
/>
</Grid>
<Grid item xs={2}>
<Box>
<TextField
id="sale-qty"
name="qty"
value={x.qty}
onChange={(e) => handleInputChange(e, i)}
variant="outlined"
fullWidth
/>
</Box>
</Grid>
<Grid item xs={3}>
<Box>
<TextField
id="sale-rate"
name="rate"
value={x.rate}
onChange={(e) => handleInputChange(e, i)}
variant="outlined"
fullWidth
/>
</Box>
</Grid>
<Grid item xs={2} sx={{ display: "flex" }}>
{inputList.length !== 1 && (
<Tooltip title="Remove">
<IconButton
onClick={() => handleRemoveClick(i)}
color="error"
>
<Remove color="error" />
</IconButton>
</Tooltip>
)}
{inputList.length - 1 === i && (
<Tooltip title="Add new">
<IconButton onClick={handleAddClick}>
<Add />
</IconButton>
</Tooltip>
)}
</Grid>
</React.Fragment>
);
})}
</Grid>
);
}
export default AddSale;
Here is screenshot how it should look like
Also codesandbox of current state
https://codesandbox.io/s/ecstatic-sunset-hxrfy?file=/src/App.js:0-3803
I want to inquire about Table Pagination in React UI Material.
Here I am trying to implement all the data from the API.
Some of the data that I have successfully implemented is from the API to the Material UI Table.
Bring up data based on request Rows Per Page
Bring up the data comes from the API that I have.
However when I try to implement Pagination, the Data doesn't appear properly from the API.
Example:
When the Component is rendered for the first time, it will display 5 data from the API. But when I tried to move to the next page, only the response from the API was successful, but not the data that appeared.
Here I divide it into several files:
Index Component
Index Container
File Index Component.
import React, { useState } from 'react'
// * Material UI
import {
Dialog,
DialogTitle,
DialogContent,
DialogContentText,
DialogActions,
Grid,
TableContainer,
Table,
TableHead,
TableRow,
TableCell,
TableBody,
TablePagination,
CssBaseline
} from '#material-ui/core'
import {
Add
} from '#material-ui/icons'
// * Core Component
import Layout from '#containers/v2/core/Layout'
import InputCategoryComponent from './Input'
import CardCore from '../../core/shared/Card'
import Controls from '../../core/shared/controls'
import { isEmpty } from '#client/libs/utils'
const columns = [
{ id: 'name', label: 'Name', minWidth: 500 },
{ id: 'Actions', label: 'Action', minWidth: 100 }
]
export default function CategoryComponent ({
page = 0,
rowsPerPage = 5,
rowsPerPageOptions = [5, 10, 15, 20, 25],
startDate = '',
endDate = '',
sortBy = 'created_at',
sortDirection = 'desc',
search = '',
totalCount = 0,
items = [],
fetch = () => {},
createPaymentCategory = () => {},
readPaymentCategory = () => {},
updatePaymentCategory = () => {},
deletePaymentCategory = () => {},
handleRowPerPage = () => {},
handlePagination = () => {}
}) {
const [isTable, setTable] = useState(true)
const [alert, setAlert] = useState(false)
const [hashed, setHashed] = useState('')
const [initialModel, setModel] = useState([])
const emptyRows = rowsPerPage - Math.min(rowsPerPage, totalCount - page * rowsPerPage)
const handleTable = (params) => {
setTable(params)
}
const handleAlertOpen = (payload) => {
setHashed(payload)
setAlert(true)
}
const handleChange = (payload) => {
if (isEmpty(payload)) {
setModel({
name: ''
})
setTable(false)
} else {
readPaymentCategory(payload).then((res) => {
setModel(res.data)
setTable(false)
})
}
}
const handleAlertClose = () => {
setAlert(false)
}
const onFinish = () => {
fetch(
page,
rowsPerPage,
startDate,
endDate,
sortBy,
sortDirection,
search
)
setTable(true)
setModel({
name: ''
})
}
const onDelete = () => {
deletePaymentCategory(hashed).then(() => {
setHashed('')
setAlert(false)
fetch(
page,
rowsPerPage,
startDate,
endDate,
sortBy,
sortDirection,
search
)
})
}
const onRowChange = (e) => {
handleRowPerPage(e.target.value)
fetch(
0,
e.target.value,
startDate,
endDate,
sortBy,
sortDirection,
search
)
}
const onPageChange = (event, newPage) => {
handlePagination(newPage)
fetch(
newPage,
rowsPerPage,
startDate,
endDate,
sortBy,
sortDirection,
search
)
}
return (
<Layout>
<CssBaseline />
{isTable && (
<Grid container>
<Grid item sm={12} md={12} lg={12}>
<CardCore
variant='info'
title='Payment Category'
>
<Grid container>
<Grid item sm={12} md={12} lg={!2}>
<Controls.Button
text='Create'
color='primary'
startIcon={<Add />}
onClick={() => handleChange()}
/>
</Grid>
</Grid>
<Grid container>
<Grid item sm={12} md={12} lg={!2}>
<TableContainer>
<Table stickyHeader aria-label='sticky table'>
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{items.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((row) => {
return (
<TableRow hover role='checkbox' tabIndex={-1} key={row.name}>
<TableCell>{row.name}</TableCell>
<TableCell align='left'>
<div>
<Controls.Button
text='Edit'
color='inherit'
onClick={() => handleChange(row.hashed_id)}
/>
<Controls.Button
text='Delete'
color='secondary'
onClick={() => handleAlertOpen(row.hashed_id)}
/>
</div>
</TableCell>
</TableRow>
)
})}
{emptyRows > 0 && (
<TableRow style={{ height: 53 * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={rowsPerPageOptions}
component='div'
count={totalCount}
rowsPerPage={rowsPerPage}
page={page}
onChangePage={onPageChange}
onChangeRowsPerPage={onRowChange}
/>
</Grid>
</Grid>
</CardCore>
</Grid>
</Grid>
)}
<Dialog
open={alert}
onClose={handleAlertClose}
fullWidth
maxWidth='sm'
aria-labelledby='alert-dialog-title'
aria-describedby='alert-dialog-description'
>
<DialogTitle id='alert-dialog-title'>Are you sure want to delete this?</DialogTitle>
<DialogContent>
<DialogContentText id='alert-dialog-description'>
You wont be able to revert this!
</DialogContentText>
</DialogContent>
<DialogActions>
<Controls.Button
text='Disagree'
color='secondary'
onClick={handleAlertClose}
/>
<Controls.Button
text='Agree'
color='primary'
autoFocus
onClick={onDelete}
/>
</DialogActions>
</Dialog>
{!isTable && (
<InputCategoryComponent
controlTable={handleTable}
initialValues={initialModel}
callBack={onFinish}
createData={createPaymentCategory}
updateData={updatePaymentCategory}
/>
)}
</Layout>
)
}
File Index Container.
import React, { Component } from 'react'
import { mapStateToProps, mapActions } from '#client/store'
import { connect } from 'react-redux'
// * Category Component
import CategoryComponent from '#components/v2/Payment/Category/Index'
class PaymentCategoryContainer extends Component {
constructor (props) {
super(props)
this.state = {
page: 0,
rowsPerPage: 5,
rowsPerPageOptions: [5, 10, 15, 20, 25],
startDate: '',
endDate: '',
sortBy: 'created_at',
sortDirection: 'desc',
search: '',
totalCount: 0,
items: []
}
this.fetch = this.fetch.bind(this)
this.handleRow = this.handleRow.bind(this)
this.handlePage = this.handlePage.bind(this)
}
fetch (page, rowsPerPage, startDate, endDate, sortBy, sortDirection, search) {
this.props.fetchPaymentCategory(
page,
rowsPerPage,
startDate,
endDate,
sortBy,
sortDirection,
search
).then((res) => {
if (res?.status === 200) {
this.setState({
items: res?.data.items,
totalCount: res?.data.totalItems
})
} else {
console.log('error')
}
})
}
handleRow (rowsPerPage) {
this.setState({
rowsPerPage: rowsPerPage
})
const { page, startDate, endDate, sortBy, sortDirection, search } = this.state
this.fetch(
page,
rowsPerPage,
startDate,
endDate,
sortBy,
sortDirection,
search
)
}
handlePage (numberOfPage) {
this.setState({
page: numberOfPage
})
const { rowsPerPage, startDate, endDate, sortBy, sortDirection, search } = this.state
this.fetch(
numberOfPage,
rowsPerPage,
startDate,
endDate,
sortBy,
sortDirection,
search
)
}
componentDidMount () {
this.fetch(
this.state.page,
this.state.rowsPerPage,
'',
'',
this.state.sortBy,
this.state.sortDirection,
''
)
}
render () {
return (
<CategoryComponent
{...this.props}
{...this.state}
fetch={this.fetch}
handleRowPerPage={this.handleRow}
handlePagination={this.handlePage}
/>
)
}
}
export default connect(
mapStateToProps('paymentCategory'),
mapActions(
'fetchPaymentCategory',
'changeRowPerPage',
'changePagination',
'createPaymentCategory',
'readPaymentCategory',
'updatePaymentCategory',
'deletePaymentCategory'
)
)(PaymentCategoryContainer)
Response data from API:
items: [] => array. totalItems: 0 => int
Are there any mistakes that I missed? or is there a step that i missed ?.
I am following the examples in this section ui material.
Thank you.
I have found where the mistake I made. I shouldn't need to slice() the data. Because I have a params page query so I just need to map() something like this.
return (
<Layout>
<CssBaseline />
{isTable && (
<Grid container>
<Grid item sm={12} md={12} lg={12}>
<CardCore
variant='info'
title='Payment Category'
>
<Grid container>
<Grid item sm={12} md={12} lg={!2}>
<Controls.Button
text='Create'
color='primary'
startIcon={<Add />}
onClick={() => handleChange()}
/>
</Grid>
</Grid>
<Grid container>
<Grid item sm={12} md={12} lg={!2}>
<TableContainer>
<Table stickyHeader aria-label='sticky table'>
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{items.map((row) => {
return (
<TableRow hover role='checkbox' tabIndex={-1} key={row.name}>
<TableCell>{row.name}</TableCell>
<TableCell align='left'>
<div>
<Controls.Button
text='Edit'
color='inherit'
onClick={() => handleChange(row.hashed_id)}
/>
<Controls.Button
text='Delete'
color='secondary'
onClick={() => handleAlertOpen(row.hashed_id)}
/>
</div>
</TableCell>
</TableRow>
)
})}
{emptyRows > 0 && (
<TableRow style={{ height: 53 * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={rowsPerPageOptions}
component='div'
count={totalCount}
rowsPerPage={rowsPerPage}
page={page}
onChangePage={onPageChange}
onChangeRowsPerPage={onRowChange}
/>
</Grid>
</Grid>
</CardCore>
</Grid>
</Grid>
)}
<Dialog
open={alert}
onClose={handleAlertClose}
fullWidth
maxWidth='sm'
aria-labelledby='alert-dialog-title'
aria-describedby='alert-dialog-description'
>
<DialogTitle id='alert-dialog-title'>Are you sure want to delete this?</DialogTitle>
<DialogContent>
<DialogContentText id='alert-dialog-description'>
You wont be able to revert this!
</DialogContentText>
</DialogContent>
<DialogActions>
<Controls.Button
text='Disagree'
color='secondary'
onClick={handleAlertClose}
/>
<Controls.Button
text='Agree'
color='primary'
autoFocus
onClick={onDelete}
/>
</DialogActions>
</Dialog>
{!isTable && (
<InputCategoryComponent
controlTable={handleTable}
initialValues={initialModel}
callBack={onFinish}
createData={createPaymentCategory}
updateData={updatePaymentCategory}
/>
)}
</Layout>
)
}
Hope this helps others.