palmpay.mx-website/src/components/EnhancedTable.js

305 lines
9.3 KiB
JavaScript

import React, { Component } from 'react';
import sortBy from 'sort-by';
import PropTypes from 'prop-types';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TablePagination from '@material-ui/core/TablePagination';
import TableRow from '@material-ui/core/TableRow';
import Checkbox from '@material-ui/core/Checkbox';
import Button from '@material-ui/core/Button';
// Custom components
import EnhancedTableHead from './EnhancedTableHead';
import EnhancedSearch from './EnhancedSearch';
const styles = {
root: {
width: '100%',
marginTop: -20,
},
table: {
minWidth: 1020,
},
tableWrapper: {
overflowX: 'auto',
},
};
/**
* This object is used for type checking the props of the component.
*/
const propTypes = {
columnData: PropTypes.array.isRequired,
data: PropTypes.array.isRequired,
orderBy: PropTypes.string.isRequired,
page: PropTypes.number,
rowsPerPage: PropTypes.number,
rowsPerPageOptions: PropTypes.array,
showSearchColumns: PropTypes.bool,
isAdmin: PropTypes.bool,
name: PropTypes.string,
onEdit: PropTypes.func,
onDelete: PropTypes.func,
onMultipleDelete: PropTypes.func,
};
/**
* This object sets default values to the optional props.
*/
const defaultProps = {
showSearchColumns: true,
page: 0,
rowsPerPage: 100,
rowsPerPageOptions: [5, 10, 25, 50, 100],
isAdmin: false,
name: 'Default Table',
onEdit: () => {},
onDelete: () => {},
onMultipleDelete: () => {},
};
/**
* The custom table used at ambassadors and merchants.
*/
class EnhancedTable extends Component {
constructor(props) {
super(props);
this.state = {
order: 'asc',
orderBy: this.props.orderBy,
selected: [],
data: this.props.data,
page: this.props.page,
rowsPerPage: this.props.rowsPerPage,
searchQuery: '',
searchColumns: this.props.columnData.filter(column => !column.disableSearch).map(column => {
return {
name: column.id,
checked: true
};
}).sort(sortBy('name'))
};
}
handleRequestSort = (event, property) => {
const orderBy = property;
let order = 'desc';
if (this.state.orderBy === property && this.state.order === 'desc') {
order = 'asc';
}
const data =
order === 'desc'
? this.state.data.sort((a, b) => (b[orderBy] < a[orderBy] ? -1 : 1))
: this.state.data.sort((a, b) => (a[orderBy] < b[orderBy] ? -1 : 1));
this.setState({ data, order, orderBy });
};
handleSelectAllClick = (event, checked) => {
if (checked) {
this.setState({ selected: this.state.data.map(n => n._id) });
return;
}
this.setState({ selected: [] });
};
handleClick = (event, id) => {
const { selected } = this.state;
const selectedIndex = selected.indexOf(id);
let newSelected = [];
if (selectedIndex === -1) {
newSelected = newSelected.concat(selected, id);
} else if (selectedIndex === 0) {
newSelected = newSelected.concat(selected.slice(1));
} else if (selectedIndex === selected.length - 1) {
newSelected = newSelected.concat(selected.slice(0, -1));
} else if (selectedIndex > 0) {
newSelected = newSelected.concat(
selected.slice(0, selectedIndex),
selected.slice(selectedIndex + 1),
);
}
this.setState({ selected: newSelected });
};
handleChangePage = (event, page) => {
this.setState({ page });
};
handleChangeRowsPerPage = event => {
this.setState({ rowsPerPage: event.target.value });
};
/**
* @description Update the query state and call the search.
* @param {string} query - The search term.
*/
updateQuery = (query) => {
query = query.trim();
// If query is empty or undefined
if (!query) {
this.setState({searchQuery: ''});
return;
}
// Update the search field as soon as the character is typed
this.setState({searchQuery: query});
};
/*
* Update the search column select box
*/
updateSearchColumn = name => () => {
const value = !(this.state.searchColumns.filter((c) => c.name === name)[0].checked);
const columns = this.state.searchColumns.filter((c) => c.name !== name);
columns.push({name: name, checked: value});
this.setState({searchColumns: columns.sort(sortBy('name'))});
};
isSelected = id => this.state.selected.indexOf(id) !== -1;
render() {
let { data } = this.props;
const { columnData, rowsPerPageOptions, showSearchColumns } = this.props;
const { order, orderBy, selected, rowsPerPage, page, searchQuery, searchColumns } = this.state;
// Logic of search query and columns
if(searchQuery.length > 0) {
data = data.filter((item) => {
let insert = false;
// Iterate over the search column select boxes
searchColumns.map(column => {
try {
if( column.checked &&
(item[column.name] !== undefined) &&
((item[column.name].toLowerCase()).indexOf(searchQuery.toLowerCase()) !== -1) ){
insert = true;
}
}
catch(error) {
//console.error(error);
}
return column;
});
if(insert){
return item;
}
return false;
});
}
return (
<div style={styles.root}>
<EnhancedSearch
query={searchQuery}
columns={searchColumns}
showSearchColumns={showSearchColumns}
onUpdateQuery={this.updateQuery}
onColumnChange={this.updateSearchColumn}
/>
<div style={styles.tableWrapper}>
<Table style={styles.table} aria-labelledby="tableTitle">
<EnhancedTableHead
columnData={columnData}
numSelected={selected.length}
order={order}
orderBy={orderBy}
onSelectAllClick={this.handleSelectAllClick}
onRequestSort={this.handleRequestSort}
rowCount={data.length}
isAdmin={this.props.isAdmin}
/>
<TableBody>
{data.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map(n => {
const isSelected = this.isSelected(n._id);
return (
<TableRow
role="checkbox"
aria-checked={false}
tabIndex={-1}
key={this.props.name + '-trow-' + n._id}
selected={false}
>
{this.props.isAdmin &&
<TableCell padding="checkbox" style={{margin: 'auto 0', textAlign: 'center', padding: 0}}>
<Checkbox checked={isSelected} onClick={event => this.handleClick(event, n._id)} />
</TableCell>
}
{this.props.columnData.map(column => (
<TableCell
key={this.props.name + '-data-' + column.id}
component="th" scope="row" padding="none"
style={{margin: 'auto 0', textAlign: 'center', padding: 0}}
>
{n[column.id]}
</TableCell>
))}
{this.props.isAdmin &&
<TableCell key={this.props.name + '-edit-' + n._id}
component="th" scope="row" padding="none"
style={{margin: 'auto 0', textAlign: 'center', padding: 0}}
>
<Button
className="App-button"
variant="contained"
color="primary"
onClick={() => this.props.onEdit(n._id)}
>Edit
</Button>
</TableCell>
}
{this.props.isAdmin &&
<TableCell key={this.props.name + '-delete-' + n._id}
component="th" scope="row" padding="none"
style={{margin: 'auto 0', textAlign: 'center', padding: 0}}
>
<Button
className="App-button"
variant="contained"
color="secondary"
onClick={() => this.props.onDelete(n._id)}
>Delete
</Button>
</TableCell>
}
</TableRow>
);
})}
</TableBody>
</Table>
</div>
<TablePagination
component="div"
count={data.length}
rowsPerPage={rowsPerPage}
rowsPerPageOptions={rowsPerPageOptions}
page={page}
backIconButtonProps={{
'aria-label': 'Previous Page',
}}
nextIconButtonProps={{
'aria-label': 'Next Page',
}}
onChangePage={this.handleChangePage}
onChangeRowsPerPage={this.handleChangeRowsPerPage}
/>
</div>
);
}
}
// Type checking the props of the component
EnhancedTable.propTypes = propTypes;
// Assign default values to the optional props
EnhancedTable.defaultProps = defaultProps;
export default EnhancedTable;