commit 2da5627eb8b7a693634e509172827f5b8487c92b
Author: Vaclav Honzik <vaclavhonzik98@gmail.com>
Date:   Fri Mar 25 22:29:07 2022 +0100

    re #9130 Catalog table component template mui doc

diff --git a/frontend/package.json b/frontend/package.json
index dfa5070..9bb63fa 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -6,6 +6,7 @@
   "dependencies": {
     "@emotion/react": "^11.8.2",
     "@emotion/styled": "^11.8.1",
+    "@mui/icons-material": "^5.5.1",
     "@mui/material": "^5.5.2",
     "@testing-library/jest-dom": "^5.14.1",
     "@testing-library/react": "^12.0.0",
diff --git a/frontend/src/api/axios.ts b/frontend/src/api/axios.ts
deleted file mode 100644
index 6ed8ce4..0000000
--- a/frontend/src/api/axios.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import axios from 'axios'
-import Config from '../config/Config'
-
-export default axios.create({
-    baseURL: Config.baseUrl,
-
-})
-
diff --git a/frontend/src/config/Config.ts b/frontend/src/config/Config.ts
deleted file mode 100644
index 64ca749..0000000
--- a/frontend/src/config/Config.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-const Config = {
-    baseUrl: process.env.REACT_APP_API_BASE_URL || 'http://localhost:8080'
-}
-
-export default Config
\ No newline at end of file
diff --git a/frontend/src/features/Auth/AuthService.ts b/frontend/src/features/Auth/AuthService.ts
deleted file mode 100644
index f56df00..0000000
--- a/frontend/src/features/Auth/AuthService.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import axios from "../../api/axios"
-import { UserDto } from "../../swagger/data-contracts"
-import ApiCallError from "../../utils/ApiCallError"
-
-export const getAccessToken = () => localStorage.getItem('accessToken') as string | null
-export const getRefreshToken = () => localStorage.getItem('refreshToken') as string | null
-
-export const setAccessToken = (accessToken: string) => localStorage.setItem('accessToken', accessToken)
-export const setRefreshToken = (refreshToken: string) => localStorage.setItem('refreshToken', refreshToken)
-
-
-export const sendRegisterRequest = (userDto: UserDto) => {
-    
-}
-
-export const sendLoginRequest = async (username: string, password: string, setLoggedInState: (loggedIn: boolean) => void) => {
-    try {
-        const { data } = await axios.post('/login', {username, password})
-
-        if (!data) {
-            throw new ApiCallError("An authentication error has occurred. Please try again later")
-        }
-
-        // TODO - set state as logged in
-        const { accessToken, refreshToken } = data
-        setAccessToken(accessToken)
-        setRefreshToken(refreshToken)
-        setLoggedInState(true)
-    }
-    catch (err) {
-
-    }
-}
\ No newline at end of file
diff --git a/frontend/src/features/Auth/Register.tsx b/frontend/src/features/Auth/Register.tsx
index e69de29..4833a02 100644
--- a/frontend/src/features/Auth/Register.tsx
+++ b/frontend/src/features/Auth/Register.tsx
@@ -0,0 +1,2 @@
+
+export default {}
\ No newline at end of file
diff --git a/frontend/src/features/Catalog/Catalog.tsx b/frontend/src/features/Catalog/Catalog.tsx
index 3fa1f71..101b1ba 100644
--- a/frontend/src/features/Catalog/Catalog.tsx
+++ b/frontend/src/features/Catalog/Catalog.tsx
@@ -1,20 +1,78 @@
+import {
+    Box,
+    Button,
+    Container,
+    Grid,
+    Paper,
+    Stack,
+    TextField,
+} from '@mui/material'
 import { useEffect, useState } from 'react'
 import { CatalogDto } from '../../swagger/data-contracts'
+import CatalogTable from './CatalogTable'
 
 const Catalog = () => {
-    // List of all catalog items
-    const [catalogItems, setCatalogItems] = useState<CatalogDto[]>([])
-
-    // Whether the request has been processed
-    const [isLoading, setIsLoading] = useState(true)
-
-    useEffect(() => {
-        
-    }, [isLoading])
+    const createRow = (): CatalogDto => ({
+        name: 'Cell',
+        certainty: 100,
+        longitude: 1,
+        latitude: 2,
+        writtenForms: ['Written Form'],
+        bibliography: ['Bibliography'],
+        countries: ['Country'],
+        alternativeNames: ['Alternative Name'],
+    })
+    const data: CatalogDto[] = Array(25).fill(createRow())
 
     return (
         <>
-            <h1>Catalog</h1>
+            <Paper sx={{ py: 2 }}>
+                <Container sx={{ mt: 4 }}>
+                    <Button variant="contained">Filter</Button>
+                    <Grid container spacing={1} alignItems="stretch">
+                        <Grid item xs={6}>
+                            <Stack
+                                direction="column"
+                                spacing={1}
+                                sx={{ mt: 2 }}
+                            >
+                                <Stack direction="row" spacing={2}>
+                                    <TextField id="name" label="Name" />
+                                    <TextField id="type" label="Type" />
+                                    <TextField
+                                        id="coordinates"
+                                        label="Coordinates"
+                                    />
+                                </Stack>
+                                <Stack direction="row" spacing={2}>
+                                    <TextField
+                                        id="writtenForm"
+                                        label="Written form"
+                                    />
+                                    <TextField
+                                        id="stateOrTerritory"
+                                        label="State or territory"
+                                    />
+                                    <TextField id="groupBy" label="Group by" />
+                                </Stack>
+                            </Stack>
+                        </Grid>
+                        <Grid item xs sx={{ mt: 'auto', ml: 1, mb: 1 }}>
+                            <Stack
+                                direction="row"
+                                justifyContent="flex-start"
+                                alignItems="flex-end"
+                            >
+                                <Button variant="outlined">Search</Button>
+                            </Stack>
+                        </Grid>
+                    </Grid>
+
+                    <Box sx={{ mt: 4 }}>
+                        <CatalogTable data={data} />
+                    </Box>
+                </Container>
+            </Paper>
         </>
     )
 }
diff --git a/frontend/src/features/Catalog/CatalogTable.tsx b/frontend/src/features/Catalog/CatalogTable.tsx
new file mode 100644
index 0000000..b39a338
--- /dev/null
+++ b/frontend/src/features/Catalog/CatalogTable.tsx
@@ -0,0 +1,214 @@
+import { useTheme } from '@mui/material/styles'
+import {
+    Box,
+    Paper,
+    Table,
+    TableBody,
+    TableCell,
+    TableContainer,
+    TableFooter,
+    TablePagination,
+    TableRow,
+} from '@mui/material'
+import TablePaginationActions, { TablePaginationActionsProps } from '@mui/material/TablePagination/TablePaginationActions'
+import { FunctionComponent, useState } from 'react'
+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 { CatalogDto } from '../../swagger/data-contracts'
+
+
+const CatalogTableActions: FunctionComponent<TablePaginationActionsProps> = ({
+    count,
+    page,
+    rowsPerPage,
+    onPageChange: onChangePage,
+}) => {
+    const theme = useTheme()
+
+    const handleFirstPageButtonClick = (
+        event: React.MouseEvent<HTMLButtonElement>
+    ) => {
+        onChangePage(event, 0)
+    }
+
+    const handleBackButtonClick = (
+        event: React.MouseEvent<HTMLButtonElement>
+    ) => {
+        onChangePage(event, page - 1)
+    }
+
+    const handleNextButtonClick = (
+        event: React.MouseEvent<HTMLButtonElement>
+    ) => {
+        onChangePage(event, page + 1)
+    }
+
+    const handleLastPageButtonClick = (
+        event: React.MouseEvent<HTMLButtonElement>
+    ) => {
+        onChangePage(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>
+    )
+}
+
+function createData(name: string, calories: number, fat: number) {
+    return { name, calories, fat }
+}
+
+const rows = [
+    createData('Cupcake', 305, 3.7),
+    createData('Donut', 452, 25.0),
+    createData('Eclair', 262, 16.0),
+    createData('Frozen yoghurt', 159, 6.0),
+    createData('Gingerbread', 356, 16.0),
+    createData('Honeycomb', 408, 3.2),
+    createData('Ice cream sandwich', 237, 9.0),
+    createData('Jelly Bean', 375, 0.0),
+    createData('KitKat', 518, 26.0),
+    createData('Lollipop', 392, 0.2),
+    createData('Marshmallow', 318, 0),
+    createData('Nougat', 360, 19.0),
+    createData('Oreo', 437, 18.0),
+].sort((a, b) => (a.calories < b.calories ? -1 : 1))
+
+
+export interface CatalogTableProps {
+    data: CatalogDto[]
+}
+
+const CatalogTable: FunctionComponent<CatalogTableProps> = ({ data }) => {
+    const [page, setPage] = useState(0)
+    const [rowsPerPage, setRowsPerPage] = useState(5)
+
+    // Avoid a layout jump when reaching the last page with empty rows.
+    const emptyRows =
+        page > 0 ? Math.max(0, (1 + page) * rowsPerPage - rows.length) : 0
+
+    const handleChangePage = (
+        event: React.MouseEvent<HTMLButtonElement> | null,
+        newPage: number
+    ) => {
+        setPage(newPage)
+    }
+
+    const handleChangeRowsPerPage = (
+        event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
+    ) => {
+        setRowsPerPage(parseInt(event.target.value, 10))
+        setPage(0)
+    }
+
+    return (
+        <TableContainer component={Paper}>
+            <Table sx={{ minWidth: 500 }} aria-label="custom pagination table">
+                <TableBody>
+                    {(rowsPerPage > 0
+                        ? data.slice(
+                              page * rowsPerPage,
+                              page * rowsPerPage + rowsPerPage
+                          )
+                        : data
+                    ).map((row) => (
+                        <TableRow key={row.name}>
+                            <TableCell component="th" scope="row">
+                                {row.name}
+                            </TableCell>
+                            <TableCell style={{ width: 160 }} align="right">
+                                {row?.alternativeNames ? row.alternativeNames.join(', ') : ''}
+                            </TableCell>
+                            <TableCell style={{ width: 160 }} align="right">
+                                {row?.writtenForms ? row.writtenForms.join(', ') : ''}
+                            </TableCell>
+                            <TableCell style={{ width: 160 }} align="right">
+                                {row?.writtenForms ? row.writtenForms.join(', ') : ''}
+                            </TableCell>
+                        </TableRow>
+                    ))}
+                    {emptyRows > 0 && (
+                        <TableRow style={{ height: 53 * emptyRows }}>
+                            <TableCell colSpan={6} />
+                        </TableRow>
+                    )}
+                </TableBody>
+                <TableFooter>
+                    <TableRow>
+                        <TablePagination
+                            rowsPerPageOptions={[
+                                5,
+                                10,
+                                25,
+                                { label: 'All', value: -1 },
+                            ]}
+                            colSpan={3}
+                            count={rows.length}
+                            rowsPerPage={rowsPerPage}
+                            page={page}
+                            SelectProps={{
+                                inputProps: {
+                                    'aria-label': 'rows per page',
+                                },
+                                native: true,
+                            }}
+                            onPageChange={handleChangePage}
+                            onRowsPerPageChange={handleChangeRowsPerPage}
+                            ActionsComponent={CatalogTableActions}
+                        />
+                    </TableRow>
+                </TableFooter>
+            </Table>
+        </TableContainer>
+    )
+}
+
+export default CatalogTable
