dashboard table, alarm center table
This commit is contained in:
379
frontend/client-portal/src/sections/dashboard/TableList.tsx
Executable file
379
frontend/client-portal/src/sections/dashboard/TableList.tsx
Executable file
@@ -0,0 +1,379 @@
|
||||
/* ---------------------------------- @mui ---------------------------------- */
|
||||
import {
|
||||
Paper,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
TextField,
|
||||
Button,
|
||||
TableSortLabel,
|
||||
Box,
|
||||
IconButton,
|
||||
Card,
|
||||
Grid,
|
||||
Autocomplete,
|
||||
} from '@mui/material';
|
||||
import { visuallyHidden } from '@mui/utils';
|
||||
/* ---------------------------------- axios --------------------------------- */
|
||||
import axios from 'axios';
|
||||
/* ---------------------------------- react --------------------------------- */
|
||||
import { useEffect, useState } from 'react';
|
||||
/* -------------------------------- component ------------------------------- */
|
||||
import Iconify from '../../components/Iconify';
|
||||
import BaseTablePagination from '../../components/BaseTablePagination';
|
||||
/* ---------------------------------- hooks --------------------------------- */
|
||||
import useMap from '../../hooks/useMap';
|
||||
/* ---------------------------------- theme --------------------------------- */
|
||||
import palette from '../../theme/palette';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
|
||||
/* ---------------------------------- types --------------------------------- */
|
||||
|
||||
type PaginationTableProps = {
|
||||
current_page: number;
|
||||
from: number;
|
||||
last_page: number;
|
||||
links: [];
|
||||
path: string;
|
||||
per_page: number;
|
||||
to: number;
|
||||
total: number;
|
||||
};
|
||||
|
||||
type DataTableProps = {
|
||||
name: string;
|
||||
member_id: string;
|
||||
service: string;
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
status: string;
|
||||
};
|
||||
|
||||
type Order = 'asc' | 'desc';
|
||||
|
||||
interface HeadCell {
|
||||
id: string;
|
||||
align: string;
|
||||
label: string;
|
||||
isSort: boolean;
|
||||
}
|
||||
|
||||
interface EnhancedTableProps {
|
||||
onRequestSort: (event: React.MouseEvent<unknown>, property: string) => void;
|
||||
order: Order;
|
||||
orderBy: string;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------- enchanced table head -------------------------- */
|
||||
|
||||
const headCells: readonly HeadCell[] = [
|
||||
{
|
||||
id: 'member_id',
|
||||
align: 'left',
|
||||
label: 'Member ID',
|
||||
isSort: false,
|
||||
},
|
||||
{
|
||||
id: 'name',
|
||||
align: 'center',
|
||||
label: 'Name',
|
||||
isSort: false,
|
||||
},
|
||||
{
|
||||
id: 'division',
|
||||
align: 'center',
|
||||
label: 'Divisi',
|
||||
isSort: false,
|
||||
},
|
||||
{
|
||||
id: 'limit',
|
||||
align: 'center',
|
||||
label: 'Limit',
|
||||
isSort: false,
|
||||
},
|
||||
{
|
||||
id: 'status',
|
||||
align: 'center',
|
||||
label: 'Status',
|
||||
isSort: false,
|
||||
},
|
||||
];
|
||||
|
||||
function EnhancedTableHead({ order, orderBy, onRequestSort }: EnhancedTableProps) {
|
||||
const createSortHandler = (property: string) => (event: React.MouseEvent<unknown>) => {
|
||||
onRequestSort(event, property);
|
||||
};
|
||||
|
||||
return (
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
{headCells.map((headCell) => (
|
||||
<TableCell
|
||||
key={headCell.id}
|
||||
sortDirection={orderBy === headCell.id ? order : false}
|
||||
// @ts-ignore
|
||||
align={headCell.align}
|
||||
sx={{ padding: 2 }}
|
||||
>
|
||||
{headCell.isSort ? (
|
||||
<TableSortLabel
|
||||
active={orderBy === headCell.id}
|
||||
direction={orderBy === headCell.id ? order : 'asc'}
|
||||
onClick={createSortHandler(headCell.id)}
|
||||
>
|
||||
{headCell.label}
|
||||
{orderBy === headCell.id ? (
|
||||
<Box component="span" sx={visuallyHidden}>
|
||||
{order === 'desc' ? 'sorted descending' : 'sorted ascending'}
|
||||
</Box>
|
||||
) : null}
|
||||
</TableSortLabel>
|
||||
) : (
|
||||
headCell.label
|
||||
)}
|
||||
</TableCell>
|
||||
))}
|
||||
<TableCell align="center">{''}</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
export default function TableList() {
|
||||
const [order, setOrder] = useState<Order>('asc');
|
||||
const [orderBy, setOrderBy] = useState('name');
|
||||
const [customSearchParams, setCustomSearchParams] = useSearchParams();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [dataTable, setDataTable] = useState([]);
|
||||
const [dataDivision, setDataDivision] = useState([]);
|
||||
const [page, setPage] = useState(0);
|
||||
const [rowsPerPage, setRowsPerPage] = useState(10);
|
||||
const [appliedParams, setAppliedParams] = useState({});
|
||||
const [paginationTable, setPaginationTable] = useState<PaginationTableProps>({
|
||||
current_page: 0,
|
||||
from: 0,
|
||||
last_page: 0,
|
||||
links: [],
|
||||
path: '',
|
||||
per_page: 0,
|
||||
to: 0,
|
||||
total: 0,
|
||||
});
|
||||
|
||||
/* ------------------------------- handle sort ------------------------------ */
|
||||
const handleRequestSort = async (event: React.MouseEvent<unknown>, property: string) => {
|
||||
const isAsc = orderBy === property && order === 'asc';
|
||||
setOrder(isAsc ? 'desc' : 'asc');
|
||||
setOrderBy(property);
|
||||
const params = Object.fromEntries([
|
||||
...customSearchParams.entries(),
|
||||
['order', isAsc ? 'desc' : 'asc'],
|
||||
['orderBy', property],
|
||||
]);
|
||||
setAppliedParams(params);
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* ------------------------------ Search field ------------------------------ */
|
||||
const [searchText, setSearchText] = useState('');
|
||||
|
||||
const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSearchText(event.target.value);
|
||||
};
|
||||
|
||||
const handleSearchSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
setIsLoading(true);
|
||||
const params = Object.fromEntries([
|
||||
...customSearchParams.entries(),
|
||||
['page', 0],
|
||||
['search', searchText],
|
||||
]);
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
setAppliedParams(params);
|
||||
setIsLoading(false);
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* ---------------------------- table pagination ---------------------------- */
|
||||
|
||||
/* ------------------------ button change pagination ------------------------ */
|
||||
const onPageChangeHandle = async (
|
||||
event: React.MouseEvent<HTMLButtonElement> | null,
|
||||
newPage: number
|
||||
) => {
|
||||
setIsLoading(true);
|
||||
const params = Object.fromEntries([
|
||||
...customSearchParams.entries(),
|
||||
['page', newPage + 1],
|
||||
['order', order],
|
||||
['orderBy', orderBy],
|
||||
]);
|
||||
setPage(newPage);
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
setAppliedParams(params);
|
||||
setIsLoading(false);
|
||||
// setCustomSearchParams.set('page', newPage + 1);
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* --------------------------- row page per limit --------------------------- */
|
||||
const onRowsPerPageChangeHandle = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setIsLoading(true);
|
||||
setPage(0);
|
||||
const params = Object.fromEntries([
|
||||
...customSearchParams.entries(),
|
||||
['page', 0],
|
||||
['order', order],
|
||||
['orderBy', orderBy],
|
||||
['per_page', parseInt(event.target.value, 10)],
|
||||
]);
|
||||
setRowsPerPage(parseInt(event.target.value, 10));
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
setAppliedParams(params);
|
||||
setIsLoading(false);
|
||||
// setCustomSearchParams.set('per_page', parseInt(event.target.value, 10));
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
setIsLoading(true);
|
||||
|
||||
const params =
|
||||
Object.keys(appliedParams).length !== 0
|
||||
? appliedParams
|
||||
: Object.fromEntries([
|
||||
...customSearchParams.entries(),
|
||||
// ['order', order],
|
||||
// ['orderBy', orderBy],
|
||||
]);
|
||||
|
||||
const response = await axios.get('http://localhost:8001/api/dashboard', {
|
||||
params: params,
|
||||
});
|
||||
|
||||
const division = await axios.get('http://localhost:8001/api/division');
|
||||
setDataDivision(division.data);
|
||||
|
||||
setDataTable(response.data.data);
|
||||
setPaginationTable(response.data.meta);
|
||||
setRowsPerPage(response.data.meta.per_page);
|
||||
setIsLoading(false);
|
||||
})();
|
||||
}, [appliedParams, customSearchParams, order, orderBy]);
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<Grid container>
|
||||
{/* Field 1 */}
|
||||
<Grid item xs={12} paddingX="24px" paddingY="20px">
|
||||
<form onSubmit={handleSearchSubmit} style={{ width: '100%' }}>
|
||||
<TextField
|
||||
id="search-input"
|
||||
label="Search"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
onChange={handleSearch}
|
||||
value={searchText}
|
||||
/>
|
||||
</form>
|
||||
</Grid>
|
||||
{/* End Field 1 */}
|
||||
{/* Field 2 */}
|
||||
<Grid item xs={12}>
|
||||
<TableContainer component={Paper}>
|
||||
<Table aria-label="collapsible table" size="small">
|
||||
<EnhancedTableHead
|
||||
order={order}
|
||||
orderBy={orderBy}
|
||||
onRequestSort={handleRequestSort}
|
||||
/>
|
||||
<TableBody>
|
||||
{isLoading ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={6} align="center">
|
||||
Loading . . .
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : dataTable.length >= 1 ? (
|
||||
dataTable.map((row: DataTableProps, index) => (
|
||||
<TableRow key={index}>
|
||||
<TableCell align="left">{row.member_id}</TableCell>
|
||||
<TableCell align="center">{row.name}</TableCell>
|
||||
<TableCell align="center">{row.service}</TableCell>
|
||||
<TableCell align="center">{row.start_date}</TableCell>
|
||||
<TableCell align="center">
|
||||
{row.status.toLowerCase() === 'active' ? (
|
||||
<Button
|
||||
sx={{
|
||||
backgroundColor: 'rgba(84, 214, 44, 0.16)',
|
||||
color: palette.dark.success.dark,
|
||||
paddingX: 1.5,
|
||||
paddingY: 1,
|
||||
'&:hover': {
|
||||
backgroundColor: palette.light.grey[400],
|
||||
color: palette.light.grey[800],
|
||||
},
|
||||
}}
|
||||
>
|
||||
{row.status}
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
sx={{
|
||||
backgroundColor: '#CD7B2E',
|
||||
color: '#FFFF',
|
||||
paddingX: 1.5,
|
||||
paddingY: 1,
|
||||
'&:hover': {
|
||||
backgroundColor: '#BF6919',
|
||||
color: '#FFFF',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{row.status}
|
||||
</Button>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<IconButton>
|
||||
<Iconify icon="ic:baseline-more-vert" />
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={6} align="center">
|
||||
No Data Found
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
|
||||
{/* Pagination */}
|
||||
<BaseTablePagination
|
||||
count={paginationTable.total}
|
||||
onPageChange={onPageChangeHandle}
|
||||
page={page}
|
||||
rowsPerPage={rowsPerPage}
|
||||
onRowsPerPageChange={onRowsPerPageChangeHandle}
|
||||
/>
|
||||
</Grid>
|
||||
{/* End Field 2 */}
|
||||
</Grid>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user