Files
School/Anul 2/Semestrul 2/MPP/Silk Road/Silk Road Web/src/components/Search/DrugTable.tsx
T
2024-08-31 12:07:21 +03:00

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;