364 lines
11 KiB
TypeScript
364 lines
11 KiB
TypeScript
import * as React from 'react';
|
|
import { useTheme } from '@mui/material/styles';
|
|
import Box from '@mui/material/Box';
|
|
import Table from '@mui/material/Table';
|
|
import TableBody from '@mui/material/TableBody';
|
|
import TableCell from '@mui/material/TableCell';
|
|
import TableContainer from '@mui/material/TableContainer';
|
|
import TableFooter from '@mui/material/TableFooter';
|
|
import TablePagination from '@mui/material/TablePagination';
|
|
import TableRow from '@mui/material/TableRow';
|
|
import Paper from '@mui/material/Paper';
|
|
import IconButton from '@mui/material/IconButton';
|
|
import FirstPageIcon from '@mui/icons-material/FirstPage';
|
|
import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft';
|
|
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
|
|
import LastPageIcon from '@mui/icons-material/LastPage';
|
|
import {
|
|
Button,
|
|
Dialog,
|
|
DialogActions,
|
|
DialogContent,
|
|
DialogContentText,
|
|
DialogTitle,
|
|
TableHead
|
|
} from '@mui/material';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import DeleteDialog from '../Shared/DeleteDialog';
|
|
import Drug from '../../interfaces/Drug';
|
|
import { useCallback, useEffect, useState } from 'react';
|
|
import { useDispatch, useSelector } from 'react-redux';
|
|
import axios from 'axios';
|
|
import { loadDrugs } from '../../redux/slices/drugSlice';
|
|
import { getWebSocket } from '../../redux/selectors';
|
|
|
|
interface TablePaginationActionsProps {
|
|
count: number;
|
|
page: number;
|
|
rowsPerPage: number;
|
|
onPageChange: (
|
|
event: React.MouseEvent<HTMLButtonElement>,
|
|
newPage: number
|
|
) => void;
|
|
}
|
|
|
|
function TablePaginationActions(props: TablePaginationActionsProps) {
|
|
const theme = useTheme();
|
|
const { count, page, rowsPerPage, onPageChange } = props;
|
|
|
|
const handleFirstPageButtonClick = (
|
|
event: React.MouseEvent<HTMLButtonElement>
|
|
) => {
|
|
onPageChange(event, 0);
|
|
};
|
|
|
|
const handleBackButtonClick = (
|
|
event: React.MouseEvent<HTMLButtonElement>
|
|
) => {
|
|
onPageChange(event, page - 1);
|
|
};
|
|
|
|
const handleNextButtonClick = (
|
|
event: React.MouseEvent<HTMLButtonElement>
|
|
) => {
|
|
onPageChange(event, page + 1);
|
|
};
|
|
|
|
const handleLastPageButtonClick = (
|
|
event: React.MouseEvent<HTMLButtonElement>
|
|
) => {
|
|
onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
|
|
};
|
|
|
|
return (
|
|
<Box sx={{ flexShrink: 0, ml: 2.5 }}>
|
|
<IconButton
|
|
onClick={handleFirstPageButtonClick}
|
|
disabled={page === 0}
|
|
aria-label='first page'
|
|
>
|
|
{theme.direction === 'rtl' ? <LastPageIcon /> : <FirstPageIcon />}
|
|
</IconButton>
|
|
<IconButton
|
|
onClick={handleBackButtonClick}
|
|
disabled={page === 0}
|
|
aria-label='previous page'
|
|
>
|
|
{theme.direction === 'rtl' ? (
|
|
<KeyboardArrowRight />
|
|
) : (
|
|
<KeyboardArrowLeft />
|
|
)}
|
|
</IconButton>
|
|
<IconButton
|
|
onClick={handleNextButtonClick}
|
|
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
|
|
aria-label='next page'
|
|
>
|
|
{theme.direction === 'rtl' ? (
|
|
<KeyboardArrowLeft />
|
|
) : (
|
|
<KeyboardArrowRight />
|
|
)}
|
|
</IconButton>
|
|
<IconButton
|
|
onClick={handleLastPageButtonClick}
|
|
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
|
|
aria-label='last page'
|
|
>
|
|
{theme.direction === 'rtl' ? <FirstPageIcon /> : <LastPageIcon />}
|
|
</IconButton>
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
const DrugTable = () => {
|
|
const dispatch = useDispatch();
|
|
const [page, setPage] = useState(
|
|
sessionStorage.getItem('page')
|
|
? parseInt(sessionStorage.getItem('page') as string)
|
|
: 0
|
|
);
|
|
const ws = useSelector(getWebSocket);
|
|
|
|
const [sort, setSort] = useState('');
|
|
const [open, setOpen] = useState(-1);
|
|
const [drugs, setDrugs] = useState<Drug[]>([]);
|
|
const [total, setTotal] = useState(0);
|
|
const [error, setError] = useState(false);
|
|
|
|
const navigate = useNavigate();
|
|
|
|
const handleViewClick = (id: number) => {
|
|
navigate(`/details/${id}`);
|
|
};
|
|
const handleUpdateClick = (id: number) => {
|
|
navigate(`/update/${id}`);
|
|
};
|
|
|
|
const handleDeleteClick = (id: number) => {
|
|
setOpen(id);
|
|
};
|
|
|
|
const [rowsPerPage, setRowsPerPage] = React.useState(
|
|
sessionStorage.getItem('rowsPerPage')
|
|
? parseInt(sessionStorage.getItem('rowsPerPage') as string, 10)
|
|
: 5
|
|
);
|
|
|
|
const emptyRows =
|
|
page > 0 ? Math.max(0, (1 + page) * rowsPerPage - total) : 0;
|
|
|
|
const handleChangePage = (
|
|
_event: React.MouseEvent<HTMLButtonElement> | null,
|
|
newPage: number
|
|
) => {
|
|
setPage(newPage);
|
|
sessionStorage.setItem('page', newPage.toString());
|
|
};
|
|
|
|
const handleChangeRowsPerPage = (
|
|
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
|
|
) => {
|
|
setRowsPerPage(parseInt(event.target.value, 10));
|
|
setPage(0);
|
|
sessionStorage.setItem('rowsPerPage', event.target.value);
|
|
};
|
|
|
|
const fetchData = useCallback(async () => {
|
|
try {
|
|
const response = await axios.get(
|
|
`https://silkroadapi.azurewebsites.net/Drug/get-drugs?Page=${
|
|
page + 1
|
|
}&PageSize=${rowsPerPage}&sorting=${sort}`,
|
|
{ withCredentials: true }
|
|
);
|
|
dispatch(loadDrugs(response.data.items));
|
|
setDrugs(response.data.items);
|
|
setTotal(response.data.total);
|
|
} catch (err) {
|
|
console.error(err);
|
|
setError(true);
|
|
}
|
|
}, [dispatch, page, rowsPerPage, sort]);
|
|
|
|
useEffect(() => {
|
|
fetchData();
|
|
}, [page, sort, dispatch, rowsPerPage, fetchData]);
|
|
|
|
useEffect(() => {
|
|
console.log(ws);
|
|
ws?.addEventListener('message', (event) => {
|
|
console.log(event.data);
|
|
fetchData();
|
|
});
|
|
}, [fetchData, ws]);
|
|
|
|
return (
|
|
<TableContainer component={Paper}>
|
|
<Table sx={{ minWidth: 500 }} aria-label='custom pagination table'>
|
|
<TableHead>
|
|
<TableRow>
|
|
<TableCell
|
|
data-asc={'false'}
|
|
onClick={(e) => {
|
|
setSort(
|
|
e.currentTarget.dataset.asc === 'false' ? 'name' : 'name_desc'
|
|
);
|
|
e.currentTarget.dataset.asc =
|
|
e.currentTarget.dataset.asc === 'false' ? 'true' : 'false';
|
|
}}
|
|
sx={{ cursor: 'pointer' }}
|
|
>
|
|
Name
|
|
</TableCell>
|
|
<TableCell
|
|
align='right'
|
|
onClick={(e) => {
|
|
setSort(
|
|
e.currentTarget.dataset.asc === 'false'
|
|
? 'manufacturer'
|
|
: 'manufacturer_desc'
|
|
);
|
|
e.currentTarget.dataset.asc =
|
|
e.currentTarget.dataset.asc === 'false' ? 'true' : 'false';
|
|
}}
|
|
sx={{ cursor: 'pointer' }}
|
|
>
|
|
Manufacturer
|
|
</TableCell>
|
|
<TableCell
|
|
align='right'
|
|
onClick={(e) => {
|
|
setSort(
|
|
e.currentTarget.dataset.asc === 'false'
|
|
? 'price'
|
|
: 'price_desc'
|
|
);
|
|
e.currentTarget.dataset.asc =
|
|
e.currentTarget.dataset.asc === 'false' ? 'true' : 'false';
|
|
}}
|
|
sx={{ cursor: 'pointer' }}
|
|
>
|
|
Price (USD)
|
|
</TableCell>
|
|
<TableCell align='right'>View</TableCell>
|
|
<TableCell align='right'>Update</TableCell>
|
|
<TableCell align='right'>Delete</TableCell>
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{drugs.map((drug) => (
|
|
<TableRow key={drug.id}>
|
|
<TableCell component='th' scope='row'>
|
|
{drug.name}
|
|
</TableCell>
|
|
<TableCell style={{ width: 160 }} align='right'>
|
|
{drug.manufacturer}
|
|
</TableCell>
|
|
<TableCell style={{ width: 160 }} align='right'>
|
|
${drug.price}
|
|
</TableCell>
|
|
<TableCell style={{ width: 160 }} align='right'>
|
|
<Button
|
|
variant='outlined'
|
|
onClick={() => {
|
|
handleViewClick(drug.id);
|
|
}}
|
|
>
|
|
View
|
|
</Button>
|
|
</TableCell>
|
|
<TableCell style={{ width: 160 }} align='right'>
|
|
<Button
|
|
variant='outlined'
|
|
onClick={() => {
|
|
handleUpdateClick(drug.id);
|
|
}}
|
|
>
|
|
Update
|
|
</Button>
|
|
</TableCell>
|
|
<TableCell style={{ width: 160 }} align='right'>
|
|
<Button
|
|
variant='outlined'
|
|
onClick={() => {
|
|
handleDeleteClick(drug.id);
|
|
}}
|
|
>
|
|
Delete
|
|
</Button>
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
{emptyRows > 0 && (
|
|
<TableRow style={{ height: 53 * emptyRows }}>
|
|
<TableCell colSpan={6} />
|
|
</TableRow>
|
|
)}
|
|
</TableBody>
|
|
<TableFooter>
|
|
<TableRow>
|
|
<TablePagination
|
|
rowsPerPageOptions={[5, 10, 25]}
|
|
colSpan={3}
|
|
count={total}
|
|
rowsPerPage={rowsPerPage}
|
|
page={page}
|
|
slotProps={{
|
|
select: {
|
|
inputProps: {
|
|
'aria-label': 'rows per page'
|
|
},
|
|
native: true
|
|
}
|
|
}}
|
|
onPageChange={handleChangePage}
|
|
onRowsPerPageChange={handleChangeRowsPerPage}
|
|
ActionsComponent={TablePaginationActions}
|
|
/>
|
|
</TableRow>
|
|
</TableFooter>
|
|
</Table>
|
|
<DeleteDialog
|
|
id={open}
|
|
handleClose={() => {
|
|
setOpen(-1);
|
|
}}
|
|
handleAgree={async () => {
|
|
await axios.delete(
|
|
`https://silkroadapi.azurewebsites.net/Drug/delete-drug/${open}`,
|
|
{ withCredentials: true }
|
|
);
|
|
await fetchData();
|
|
setOpen(-1);
|
|
}}
|
|
/>
|
|
<Dialog
|
|
open={error}
|
|
aria-labelledby='alert-dialog-title'
|
|
aria-describedby='alert-dialog-description'
|
|
>
|
|
<DialogTitle id='alert-dialog-title'>{'Error'}</DialogTitle>
|
|
<DialogContent>
|
|
<DialogContentText id='alert-dialog-description'>
|
|
Error while connecting
|
|
</DialogContentText>
|
|
</DialogContent>
|
|
<DialogActions>
|
|
<Button
|
|
onClick={() => {
|
|
setError(false);
|
|
}}
|
|
color='primary'
|
|
>
|
|
Close
|
|
</Button>
|
|
</DialogActions>
|
|
</Dialog>
|
|
</TableContainer>
|
|
);
|
|
};
|
|
|
|
export default DrugTable;
|