Skip to content

Commit 0b1bd22

Browse files
authored
Merge pull request #2 from Lemoncode/feature/plumbing-table
add table component and install dependencies
2 parents cfbad1f + b9fdc5a commit 0b1bd22

36 files changed

Lines changed: 1963 additions & 152 deletions

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module.exports = {
1111
'@typescript-eslint/no-explicit-any': 'off',
1212
'@typescript-eslint/explicit-function-return-type': 'off',
1313
'react/prop-types': 'off',
14+
'react/jsx-key': 'off',
1415
},
1516
settings: {
1617
react: {

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,15 @@
4242
"@lemoncode/fonk": "^1.3.0",
4343
"@lemoncode/fonk-final-form": "^2.3.1",
4444
"@lemoncode/fonk-match-field-validator": "^1.0.1",
45-
"@material-ui/core": "^4.7.0",
46-
"@material-ui/icons": "^4.5.1",
45+
"@material-ui/core": "4.9.11",
46+
"@material-ui/icons": "^4.9.1",
47+
"@material-ui/lab": "4.0.0-alpha.47",
4748
"axios": "^0.19.0",
4849
"emotion": "^10.0.23",
4950
"final-form": "^4.18.6",
5051
"graphql-request": "^1.8.2",
5152
"lodash.flowright": "^3.5.0",
53+
"lodash.get": "^4.4.2",
5254
"lodash.merge": "^4.6.2",
5355
"react": "^16.12.0",
5456
"react-dom": "^16.12.0",
@@ -57,6 +59,7 @@
5759
"react-promise-tracker": "^2.0.5",
5860
"react-router-dom": "^5.1.2",
5961
"react-spinners": "^0.6.1",
62+
"react-table": "^7.0.4",
6063
"regenerator-runtime": "^0.13.3"
6164
},
6265
"devDependencies": {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import React from 'react';
2+
import Dialog from '@material-ui/core/Dialog';
3+
import DialogTitle from '@material-ui/core/DialogTitle';
4+
import DialogContent from '@material-ui/core/DialogContent';
5+
import DialogActions from '@material-ui/core/DialogActions';
6+
import Button from '@material-ui/core/Button';
7+
8+
interface LabelProps {
9+
closeButton: string;
10+
acceptButton: string;
11+
}
12+
13+
interface Props {
14+
isOpen: boolean;
15+
onAccept: () => void;
16+
onClose: () => void;
17+
title: string | React.ReactNode;
18+
labels: LabelProps;
19+
}
20+
21+
export const ConfirmationDialogComponent: React.FunctionComponent<Props> = props => {
22+
const { isOpen, onAccept, onClose, title, labels, children } = props;
23+
24+
const handleAccept = () => {
25+
onAccept();
26+
onClose();
27+
};
28+
29+
return (
30+
<Dialog open={isOpen}>
31+
<DialogTitle>{title}</DialogTitle>
32+
<DialogContent>{children}</DialogContent>
33+
<DialogActions>
34+
<Button onClick={onClose} color="secondary" variant="contained">
35+
{labels.closeButton}
36+
</Button>
37+
<Button onClick={handleAccept} color="primary" variant="contained">
38+
{labels.acceptButton}
39+
</Button>
40+
</DialogActions>
41+
</Dialog>
42+
);
43+
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import React from 'react';
2+
import { createEmptyLookup, Lookup } from 'common/models';
3+
4+
export const useConfirmationDialog = () => {
5+
const [isOpen, setIsOpen] = React.useState(false);
6+
const [itemToDelete, setItemToDelete] = React.useState(createEmptyLookup());
7+
8+
return {
9+
isOpen,
10+
itemToDelete,
11+
onAccept: () => {
12+
setItemToDelete(createEmptyLookup());
13+
},
14+
onClose: () => setIsOpen(false),
15+
onOpenDialog: (item: Lookup) => {
16+
setIsOpen(true);
17+
setItemToDelete(item);
18+
},
19+
};
20+
};
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './confirmation-dialog.component';
2+
export * from './confirmation-dialog.hook';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './pagination.component';
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React from 'react';
2+
import Pagination from '@material-ui/lab/Pagination';
3+
4+
interface Props {
5+
pageIndex: number;
6+
pageCount: number;
7+
onChange: (pageIndex: number) => void;
8+
className?: string;
9+
}
10+
11+
export const PaginationComponent: React.FunctionComponent<Props> = props => {
12+
const { pageIndex, pageCount, onChange, className } = props;
13+
14+
const handleChange = (event, value) => {
15+
onChange(value - 1);
16+
};
17+
18+
return (
19+
<Pagination
20+
className={className}
21+
color="primary"
22+
count={pageCount}
23+
page={pageIndex + 1}
24+
onChange={handleChange}
25+
/>
26+
);
27+
};
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './search-bar.component';
2+
export * from './search-bar.hook';
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import React from 'react';
2+
import TextField from '@material-ui/core/TextField';
3+
import SearchIcon from '@material-ui/icons/Search';
4+
5+
interface LabelProps {
6+
placeholder: string;
7+
}
8+
9+
interface Props {
10+
search: string;
11+
onSearch: (search: string) => void;
12+
labels: LabelProps;
13+
className?: string;
14+
}
15+
16+
export const SearchBarComponent: React.FunctionComponent<Props> = props => {
17+
const { search, onSearch, labels, className } = props;
18+
19+
return (
20+
<TextField
21+
className={className}
22+
value={search}
23+
onChange={e => onSearch(e.target.value)}
24+
placeholder={labels.placeholder}
25+
InputProps={{
26+
startAdornment: <SearchIcon />,
27+
}}
28+
/>
29+
);
30+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from 'react';
2+
import { useDebounce } from 'common/hooks';
3+
import { filterByText } from 'common/helpers';
4+
5+
export const useSearchBar = <Entity, Key extends keyof Entity>(
6+
collection: Entity[],
7+
fields: Key[] | string[]
8+
) => {
9+
const [search, setSearch] = React.useState('');
10+
const [filteredList, setFilteredList] = React.useState<Entity[]>(collection);
11+
React.useEffect(() => {
12+
setFilteredList(collection);
13+
}, [collection]);
14+
15+
const debouncedSearch = useDebounce(search, 250);
16+
React.useEffect(() => {
17+
const newFilteredList = filterByText(collection, debouncedSearch, fields);
18+
setFilteredList(newFilteredList);
19+
}, [debouncedSearch]);
20+
21+
return {
22+
search,
23+
onSearch: setSearch,
24+
filteredList,
25+
};
26+
};

0 commit comments

Comments
 (0)