dashboard table, alarm center table

This commit is contained in:
Muhammad Fajar
2022-12-02 15:31:50 +07:00
parent e83a6784f3
commit 3dc3c474eb
13 changed files with 938 additions and 607 deletions

View File

@@ -1,7 +1,7 @@
/* ---------------------------------- react --------------------------------- */
import { useState, SyntheticEvent } from 'react';
/* ---------------------------------- @mui ---------------------------------- */
import { Box, Tabs, Tab, Container, Grid, Card, Typography } from '@mui/material';
import { Box, Tabs, Tab, Container, Grid, Card } from '@mui/material';
import { styled } from '@mui/material/styles';
/* ------------------------------- components ------------------------------- */
import Page from '../../components/Page';
@@ -43,11 +43,7 @@ function TabPanel(props: TabPanelProps) {
aria-labelledby={`simple-tab-${index}`}
{...other}
>
{value === index && (
<Box>
<Typography>{children}</Typography>
</Box>
)}
{value === index && <Box>{children}</Box>}
</div>
);
}

View File

@@ -1,4 +1,4 @@
// @mui
/* ---------------------------------- @mui ---------------------------------- */
import {
Paper,
Table,
@@ -9,101 +9,322 @@ import {
TableRow,
TextField,
Stack,
Button,
TableSortLabel,
Box,
} from '@mui/material';
// hooks
import React, { ChangeEvent, useEffect, useRef, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
// components
import axios from '../../utils/axios';
import BasePagination from '../../components/BasePagination';
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';
/* ---------------------------------- 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;
};
/* -------------------------------------------------------------------------- */
/* -------------------------- enchanced table head -------------------------- */
type Order = 'asc' | 'desc';
interface HeadCell {
id: string;
label: string;
}
const headCells: readonly HeadCell[] = [
{
id: 'name',
label: 'Name',
},
{
id: 'member_id',
label: 'Member ID',
},
{
id: 'service',
label: 'Service',
},
{
id: 'start_date',
label: 'Start Date',
},
{
id: 'end_date',
label: 'End Date',
},
{
id: 'status',
label: 'Status',
},
];
interface EnhancedTableProps {
onRequestSort: (event: React.MouseEvent<unknown>, property: string) => void;
order: Order;
orderBy: string;
}
function EnhancedTableHead(props: EnhancedTableProps) {
const { order, orderBy, onRequestSort } = props;
const createSortHandler = (property: string) => (event: React.MouseEvent<unknown>) => {
onRequestSort(event, property);
};
return (
<TableHead>
<TableRow>
<TableCell align="center">No</TableCell>
{headCells.map((headCell) => (
<TableCell
key={headCell.id}
sortDirection={orderBy === headCell.id ? order : false}
align="center"
>
<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>
</TableCell>
))}
</TableRow>
</TableHead>
);
}
/* -------------------------------------------------------------------------- */
export default function List() {
const [searchParams, setSearchParams] = useSearchParams();
const [order, setOrder] = useState<Order>('asc');
const [orderBy, setOrderBy] = useState('name');
const [customSearchParams, setCustomSearchParams] = useMap<string, any>();
const [isLoading, setIsLoading] = useState(true);
const [dataTable, setDataTable] = useState([]);
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10);
const [paginationTable, setPaginationTable] = useState<PaginationTableProps>({
current_page: 0,
from: 0,
last_page: 0,
links: [],
path: '',
per_page: 0,
to: 0,
total: 0,
});
function SearchInput(props: any) {
// SEARCH
const searchInput = useRef<HTMLInputElement>(null);
const [searchText, setSearchText] = useState('');
const handleSearchChange = (event: any) => {
const newSearchText = event.target.value ?? '';
setSearchText(newSearchText);
};
const handleSearchSubmit = (event: any) => {
event.preventDefault();
props.onSearch(searchText); // Trigger to Parent
};
useEffect(() => {
// Trigger First Search
setSearchText(searchParams.get('search') ?? '');
}, []);
return (
<form onSubmit={handleSearchSubmit} style={{ width: '100%', padding: '20px 24px' }}>
<TextField
id="search-input"
ref={searchInput}
label="Search"
variant="outlined"
fullWidth
onChange={handleSearchChange}
value={searchText}
/>
</form>
);
}
const headStyle = {
fontWeight: 'bold',
/* ------------------------------- 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],
]);
setIsLoading(true);
await new Promise((resolve) => setTimeout(resolve, 500));
loadDataTable(params);
setIsLoading(false);
};
/* -------------------------------------------------------------------------- */
/* ------------------------------ Search field ------------------------------ */
const [searchText, setSearchText] = useState('');
const handleSearch = (event: any) => {
setSearchText(event.target.value);
};
const handleSearchSubmit = async (event: any) => {
event.preventDefault();
const params = Object.fromEntries([...customSearchParams.entries(), ['search', searchText]]);
setIsLoading(true);
await new Promise((resolve) => setTimeout(resolve, 500));
loadDataTable(params);
setIsLoading(false);
};
/* -------------------------------------------------------------------------- */
/* --------------------------- Load Data Table API -------------------------- */
const loadDataTable = async (appliedParams: any | null = null) => {
setIsLoading(true);
const params = appliedParams
? appliedParams
: Object.fromEntries([
...customSearchParams.entries(),
['order', order],
['orderBy', orderBy],
]);
const response = await axios.get('http://localhost:8001/api/alarm-center', { params: params });
setDataTable(response.data.data);
setPaginationTable(response.data.meta);
setRowsPerPage(response.data.meta.per_page);
setIsLoading(false);
};
/* -------------------------------------------------------------------------- */
/* ------------------------ button change pagination ------------------------ */
const onPageChangeHandle = async (event: unknown, newPage: number) => {
const params = Object.fromEntries([...customSearchParams.entries(), ['page', newPage + 1]]);
setPage(newPage);
setIsLoading(true);
await new Promise((resolve) => setTimeout(resolve, 500));
loadDataTable(params);
setIsLoading(false);
setCustomSearchParams.set('page', newPage + 1);
};
/* -------------------------------------------------------------------------- */
/* ----------------------- row page per limit on click ---------------------- */
const onRowsPerPageChangeHandle = async (event: React.ChangeEvent<HTMLInputElement>) => {
setPage(0);
const params = Object.fromEntries([
...customSearchParams.entries(),
['page', 0],
['per_page', parseInt(event.target.value, 10)],
]);
setRowsPerPage(parseInt(event.target.value, 10));
setIsLoading(true);
await new Promise((resolve) => setTimeout(resolve, 500));
loadDataTable(params);
setIsLoading(false);
setCustomSearchParams.set('per_page', parseInt(event.target.value, 10));
};
/* -------------------------------------------------------------------------- */
useEffect(() => {
loadDataTable();
}, []);
return (
<Stack>
{/* Search */}
<SearchInput />
<form onSubmit={handleSearchSubmit} style={{ width: '100%', padding: '20px 24px' }}>
<TextField
id="search-input"
label="Search"
variant="outlined"
fullWidth
onChange={handleSearch}
value={searchText}
/>
</form>
{/* The Main Table */}
<TableContainer component={Paper}>
<Table aria-label="collapsible table">
<TableHead>
<TableRow>
<TableCell style={headStyle} align="left">
No
</TableCell>
<TableCell style={headStyle} align="left">
Name
</TableCell>
<TableCell style={headStyle} align="left">
Member ID
</TableCell>
<TableCell style={headStyle} align="left">
Service
</TableCell>
<TableCell style={headStyle} align="left">
Start Date
</TableCell>
<TableCell style={headStyle} align="left">
End Date
</TableCell>
<TableCell style={headStyle} align="right" width={100}>
Status
</TableCell>
</TableRow>
</TableHead>
<EnhancedTableHead order={order} orderBy={orderBy} onRequestSort={handleRequestSort} />
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">
No Data
</TableCell>
</TableRow>
{isLoading ? (
<TableRow>
<TableCell colSpan={8} align="center">
Loading . . .
</TableCell>
</TableRow>
) : dataTable.length >= 1 ? (
dataTable.map((row: DataTableProps, index) => (
<TableRow key={index}>
<TableCell align="center">{paginationTable.from + index++}</TableCell>
<TableCell align="center">{row.name}</TableCell>
<TableCell align="center">{row.member_id}</TableCell>
<TableCell align="center">{row.service}</TableCell>
<TableCell align="center">{row.start_date}</TableCell>
<TableCell align="center">{row.end_date}</TableCell>
<TableCell align="center">
{row.status.toLowerCase() === 'done' ? (
<Button
startIcon={<Iconify icon="ic:round-check" />}
sx={{
backgroundColor: palette.light.grey[300],
color: palette.light.grey[800],
paddingX: 1.5,
paddingY: 1,
'&:hover': {
backgroundColor: palette.light.grey[400],
color: palette.light.grey[800],
},
}}
>
{row.status}
</Button>
) : (
<Button
startIcon={<Iconify icon="fa6-solid:clock" />}
sx={{
backgroundColor: '#CD7B2E',
color: '#FFFF',
paddingX: 1.5,
paddingY: 1,
'&:hover': {
backgroundColor: '#BF6919',
color: '#FFFF',
},
}}
>
{row.status}
</Button>
)}
</TableCell>
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={8} align="center">
No Data Found
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</TableContainer>
{/* Pagination */}
{/* <BasePagination onPageChange={handlePageChange} /> */}
<BaseTablePagination
count={paginationTable.total}
onPageChange={onPageChangeHandle}
page={page}
rowsPerPage={rowsPerPage}
onRowsPerPageChange={onRowsPerPageChangeHandle}
/>
</Stack>
);
}