269 lines
9.5 KiB
TypeScript
269 lines
9.5 KiB
TypeScript
/* ---------------------------------- @mui ---------------------------------- */
|
|
import { styled } from '@mui/material/styles';
|
|
import {
|
|
Paper,
|
|
Table as TableContent,
|
|
TableBody,
|
|
TableCell,
|
|
TableContainer,
|
|
TableHead,
|
|
TableRow,
|
|
TextField,
|
|
Button,
|
|
TableSortLabel,
|
|
Box,
|
|
Card,
|
|
Grid,
|
|
FormControl,
|
|
InputLabel,
|
|
Select,
|
|
MenuItem,
|
|
SelectChangeEvent,
|
|
Stack,
|
|
Typography,
|
|
LinearProgress,
|
|
linearProgressClasses,
|
|
} from '@mui/material';
|
|
import { visuallyHidden } from '@mui/utils';
|
|
/* ---------------------------------- axios --------------------------------- */
|
|
import axios from '../utils/axios';
|
|
/* ---------------------------------- react --------------------------------- */
|
|
import { Fragment, useContext, useEffect, useState } from 'react';
|
|
import { useSearchParams } from 'react-router-dom';
|
|
/* -------------------------------- component ------------------------------- */
|
|
import BaseTablePagination from './BaseTablePagination';
|
|
/* ---------------------------------- theme --------------------------------- */
|
|
import palette from '../theme/palette';
|
|
/* ---------------------------------- utils --------------------------------- */
|
|
import { UserCurrentCorporateContext } from '../contexts/UserCurrentCorporate';
|
|
import { fSplit } from '../utils/formatNumber';
|
|
/* ---------------------------------- types --------------------------------- */
|
|
import { DivisionDataProps, Order, PaginationTableProps, TableListProps } from '../@types/table';
|
|
|
|
/* --------------------------------- styled --------------------------------- */
|
|
const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({
|
|
height: 10,
|
|
borderRadius: 6,
|
|
[`&.${linearProgressClasses.colorPrimary}`]: {
|
|
backgroundColor: '#D1F1F1',
|
|
},
|
|
[`& .${linearProgressClasses.bar}`]: {
|
|
borderRadius: 6,
|
|
backgroundColor: theme.palette.primary.main,
|
|
},
|
|
}));
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
export default function Table<T>({
|
|
headCells,
|
|
rows,
|
|
paginations,
|
|
orders,
|
|
loadings,
|
|
params,
|
|
filters,
|
|
searchs,
|
|
}: TableListProps<T>) {
|
|
/* ------------------------------- handle sort ------------------------------ */
|
|
const handleRequestSort = async (event: React.MouseEvent<unknown>, property: string) => {
|
|
const isAsc = orders?.orderBy === property && orders?.order === 'asc';
|
|
|
|
orders?.setOrder(isAsc ? 'desc' : 'asc');
|
|
orders?.setOrderBy(property);
|
|
const parameters = Object.fromEntries([
|
|
...params.searchParams.entries(),
|
|
['order', isAsc ? 'desc' : 'asc'],
|
|
['orderBy', property],
|
|
]);
|
|
params.setAppliedParams(parameters);
|
|
};
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
/* -------------------------- enchanced table head -------------------------- */
|
|
const EnhancedTableHead = () => {
|
|
const createSortHandler = (property: string) => (event: React.MouseEvent<unknown>) => {
|
|
handleRequestSort(event, property);
|
|
};
|
|
|
|
return (
|
|
<TableHead>
|
|
<TableRow>
|
|
{headCells &&
|
|
headCells.map((headCell, index) => (
|
|
<TableCell
|
|
key={index}
|
|
sortDirection={orders?.orderBy === headCell.id ? orders.order : false}
|
|
// @ts-ignore
|
|
align={headCell.align}
|
|
sx={{ padding: 2 }}
|
|
width={headCell.width ? headCell.width : 'auto'}
|
|
>
|
|
{headCell.isSort ? (
|
|
<TableSortLabel
|
|
active={orders?.orderBy === headCell.id}
|
|
direction={orders?.orderBy === headCell.id ? orders.order : 'asc'}
|
|
onClick={createSortHandler(headCell.id)}
|
|
>
|
|
{headCell.label}
|
|
{orders?.orderBy === headCell.id ? (
|
|
<Box component="span" sx={visuallyHidden}>
|
|
{orders.order === 'desc' ? 'sorted descending' : 'sorted ascending'}
|
|
</Box>
|
|
) : null}
|
|
</TableSortLabel>
|
|
) : (
|
|
headCell.label
|
|
)}
|
|
</TableCell>
|
|
))}
|
|
</TableRow>
|
|
</TableHead>
|
|
);
|
|
};
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
/* ------------------------ button change pagination ------------------------ */
|
|
const onPageChangeHandle = async (
|
|
event: React.MouseEvent<HTMLButtonElement> | null,
|
|
newPage: number
|
|
) => {
|
|
const parameters = Object.fromEntries([
|
|
...params.searchParams.entries(),
|
|
['page', newPage + 1],
|
|
]);
|
|
paginations.setPage(newPage);
|
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
params.setAppliedParams(parameters);
|
|
};
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
/* --------------------------- row page per limit --------------------------- */
|
|
const onRowsPerPageChangeHandle = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
params.searchParams.delete('page');
|
|
const parameters = Object.fromEntries([
|
|
...params.searchParams.entries(),
|
|
['per_page', parseInt(event.target.value, 10)],
|
|
]);
|
|
|
|
paginations.setPage(0);
|
|
paginations.setRowsPerPage(parseInt(event.target.value, 10));
|
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
params.setAppliedParams(parameters);
|
|
};
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
return (
|
|
<Card>
|
|
<Grid container>
|
|
{/* Field 1 */}
|
|
<Grid item xs={12} paddingX="24px" paddingY="20px">
|
|
<Grid container spacing={2}>
|
|
{filters && filters.useFilter ? (
|
|
<Fragment>
|
|
<Grid item xs={12} lg={3} xl={2}>
|
|
<FormControl fullWidth>
|
|
<InputLabel id="simple-division-select-lable">Division</InputLabel>
|
|
<Select
|
|
labelId="simple-division-select-lable"
|
|
id="division-select-lable"
|
|
value={filters.config.divisionValue}
|
|
label="Division"
|
|
onChange={filters.config.handleDivisionChange}
|
|
>
|
|
<MenuItem value="all">All</MenuItem>
|
|
{filters.config.divisionData.map((row: DivisionDataProps, index) => (
|
|
<MenuItem key={index} value={row.id}>
|
|
{row.name}
|
|
</MenuItem>
|
|
))}
|
|
</Select>
|
|
</FormControl>
|
|
</Grid>
|
|
<Grid item xs={12} lg={9} xl={10}>
|
|
<form onSubmit={searchs.handleSearchSubmit}>
|
|
<TextField
|
|
id="search-input"
|
|
label="Search"
|
|
variant="outlined"
|
|
onChange={(event) => searchs.setSearchText(event.target.value)}
|
|
value={searchs.searchText}
|
|
fullWidth
|
|
/>
|
|
</form>
|
|
</Grid>
|
|
</Fragment>
|
|
) : (
|
|
<Grid item xs={12}>
|
|
<form onSubmit={searchs.handleSearchSubmit}>
|
|
<TextField
|
|
id="search-input"
|
|
label="Search"
|
|
variant="outlined"
|
|
onChange={(event) => searchs.setSearchText(event.target.value)}
|
|
value={searchs.searchText}
|
|
fullWidth
|
|
/>
|
|
</form>
|
|
</Grid>
|
|
)}
|
|
</Grid>
|
|
</Grid>
|
|
{/* End Field 1 */}
|
|
{/* Field 2 */}
|
|
<Grid item xs={12}>
|
|
{/* Table */}
|
|
<TableContainer component={Paper}>
|
|
<TableContent aria-label="collapsible table" size="small">
|
|
{/* Table Header */}
|
|
<EnhancedTableHead />
|
|
{/* End Table Header */}
|
|
{/* Table Body */}
|
|
<TableBody>
|
|
{loadings.isLoading ? (
|
|
<TableRow>
|
|
<TableCell colSpan={headCells?.length} align="center">
|
|
Loading . . .
|
|
</TableCell>
|
|
</TableRow>
|
|
) : rows && rows.length >= 1 ? (
|
|
rows.map((row, rowIndex) => (
|
|
<TableRow key={rowIndex}>
|
|
{headCells &&
|
|
//@ts-ignore
|
|
headCells.map((head, headIndex) => (
|
|
//@ts-ignore
|
|
<TableCell align={head.align} key={headIndex}>
|
|
{row[head.id]}
|
|
</TableCell>
|
|
))}
|
|
</TableRow>
|
|
))
|
|
) : (
|
|
<TableRow>
|
|
<TableCell colSpan={6} align="center">
|
|
No Data Found
|
|
</TableCell>
|
|
</TableRow>
|
|
)}
|
|
</TableBody>
|
|
{/* End Table Body */}
|
|
</TableContent>
|
|
</TableContainer>
|
|
{/* End Table */}
|
|
|
|
{/* Pagination */}
|
|
<BaseTablePagination
|
|
count={paginations.paginationTable.total}
|
|
onPageChange={onPageChangeHandle}
|
|
page={paginations.page}
|
|
rowsPerPage={paginations.rowsPerPage}
|
|
onRowsPerPageChange={onRowsPerPageChangeHandle}
|
|
/>
|
|
{/* End Pagination */}
|
|
</Grid>
|
|
{/* End Field 2 */}
|
|
</Grid>
|
|
</Card>
|
|
);
|
|
}
|