Procházet zdrojové kódy

Add filter and sort functionality

paging-sorting-filtering
mladen.dubovac před 4 roky
rodič
revize
6bc926e947

+ 80
- 14
src/components/MUI/Examples/PagingSortingFilteringExample.js Zobrazit soubor

@@ -6,6 +6,11 @@ import {
Typography,
Divider,
TablePagination,
TextField,
FormControl,
InputLabel,
Select,
MenuItem,
} from '@mui/material';
// import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector, batch } from 'react-redux';
@@ -14,11 +19,15 @@ import {
pageSelector,
itemsPerPageSelector,
countSelector,
filterSelector,
sortSelector,
} from '../../../store/selectors/randomDataSelectors';
import {
loadData,
updatePage,
updateItemsPerPage,
updateFilter,
updateSort,
} from '../../../store/actions/randomData/randomDataActions';

const PagingSortingFilteringExample = () => {
@@ -28,9 +37,12 @@ const PagingSortingFilteringExample = () => {
const currentPage = useSelector(pageSelector);
const itemsPerPage = useSelector(itemsPerPageSelector);
const totalCount = useSelector(countSelector);
const filter = useSelector(filterSelector);
const sort = useSelector(sortSelector) || 'name-asc';

useEffect(() => {
dispatch(loadData(30));
dispatch(updateSort(sort));
}, []);

const handlePageChange = (event, newPage) => {
@@ -45,31 +57,71 @@ const PagingSortingFilteringExample = () => {
});
};

const handleFilterChange = (event) => {
const filter = event.target.value;
batch(() => {
dispatch(updateFilter(filter));
currentPage > 0 && dispatch(updatePage(0));
});
};

const handleSortChange = (event) => {
const sort = event.target.value;
dispatch(updateSort(sort));
};

return (
<Paper
sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
justifyContent: 'start',
py: 2,
minHeight: 500,
}}
elevation={5}
>
<Typography sx={{ my: 4 }} variant="h4" gutterBottom align="center">
Pagination, Filtering and Sorting Example
</Typography>
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
<Box>
<TablePagination
component="div"
count={totalCount}
page={currentPage}
onPageChange={handlePageChange}
rowsPerPage={itemsPerPage}
onRowsPerPageChange={handleItemsPerPageChange}
rowsPerPageOptions={[12, 24, 48, 96]}
labelRowsPerPage="Items per page"
showFirstButton
showLastButton
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
flexWrap: 'wrap',
mx: 2,
}}
>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
width: '100%',
}}
>
{/* TODO Separate into SelectComponent */}
<FormControl sx={{ flexGrow: 1 }}>
<InputLabel id="sort-label">Sort</InputLabel>
<Select
label="Sort"
labelId="sort-label"
id="sort-select-helper"
value={sort}
onChange={handleSortChange}
>
<MenuItem value="name-asc">Name - A-Z</MenuItem>
<MenuItem value="name-desc">Name - Z-A</MenuItem>
<MenuItem value="price-asc">Price - Lowest to Highest</MenuItem>
<MenuItem value="price-desc">Price - Highest to Lowest</MenuItem>
</Select>
</FormControl>
<TextField
sx={{ flexGrow: 1 }}
variant="outlined"
label="Filter"
placeholder="Filter"
value={filter}
onChange={handleFilterChange}
/>
</Box>
</Box>
@@ -101,6 +153,20 @@ const PagingSortingFilteringExample = () => {
</Grid>
))}
</Grid>
<Box sx={{ width: '100%' }}>
<TablePagination
component="div"
count={totalCount}
page={currentPage}
onPageChange={handlePageChange}
rowsPerPage={itemsPerPage}
onRowsPerPageChange={handleItemsPerPageChange}
rowsPerPageOptions={[12, 24, 48, 96]}
labelRowsPerPage="Items per page"
showFirstButton
showLastButton
/>
</Box>
</Paper>
);
};

+ 2
- 0
src/store/actions/randomData/randomDataActionConstants.js Zobrazit soubor

@@ -1,3 +1,5 @@
export const LOAD_DATA = 'LOAD_DATA';
export const UPDATE_PAGE = 'UPDATE_PAGE';
export const UPDATE_ITEMS_PER_PAGE = 'UPDATE_ITEMS_PER_PAGE';
export const UPDATE_FILTER = 'UPDATE_FILTER';
export const UPDATE_SORT = 'UPDATE_SORT';

+ 12
- 0
src/store/actions/randomData/randomDataActions.js Zobrazit soubor

@@ -2,6 +2,8 @@ import {
LOAD_DATA,
UPDATE_PAGE,
UPDATE_ITEMS_PER_PAGE,
UPDATE_FILTER,
UPDATE_SORT
} from './randomDataActionConstants';

export const loadData = (payload) => ({
@@ -18,3 +20,13 @@ export const updateItemsPerPage = (payload) => ({
type: UPDATE_ITEMS_PER_PAGE,
payload,
});

export const updateFilter = (payload) => ({
type: UPDATE_FILTER,
payload,
})

export const updateSort = (payload) => ({
type: UPDATE_SORT,
payload,
})

+ 52
- 0
src/store/reducers/randomData/randomDataReducer.js Zobrazit soubor

@@ -3,14 +3,19 @@ import {
LOAD_DATA,
UPDATE_PAGE,
UPDATE_ITEMS_PER_PAGE,
UPDATE_FILTER,
UPDATE_SORT,
} from '../../actions/randomData/randomDataActionConstants.js';
import generate from '../../../util/helpers/randomData';

const initialState = {
items: [],
filteredItems: [],
count: 0,
page: 0,
itemsPerPage: 12,
filter: '',
sort: '',
};

export default createReducer(
@@ -18,6 +23,8 @@ export default createReducer(
[LOAD_DATA]: loadRandomData,
[UPDATE_PAGE]: updatePage,
[UPDATE_ITEMS_PER_PAGE]: updateItemsPerPage,
[UPDATE_FILTER]: updateFilter,
[UPDATE_SORT]: updateSort,
},
initialState
);
@@ -29,6 +36,7 @@ function loadRandomData(state, action) {
return {
...state,
items,
filteredItems: items,
count: items.length,
};
}
@@ -50,3 +58,47 @@ function updateItemsPerPage(state, action) {
itemsPerPage,
};
}

function updateFilter(state, action) {
const filter = action.payload;
const filteredItems = filter
? state.items.filter((item) => item.name.toLowerCase().includes(filter.toLowerCase())) : state.items;

return {
...state,
filter,
filteredItems,
count: filteredItems.length,
};
}

function updateSort(state, action) {
const sort = action.payload;
const [field, direction] = sort.split('-');

const sortDirection = direction === 'asc' ? 1 : -1;
const dataItems = state.filteredItems.length
? state.filteredItems
: state.items;

const sorted = dataItems.sort((a, b) => {
if (a[field] > b[field]) {
return sortDirection;
}
if (b[field] > a[field]) {
return sortDirection * -1;
}
});

const items = state.items.length ? sorted : state.items;
const filteredItems = state.filteredItems.length
? sorted
: state.filteredItems;

return {
...state,
sort,
items,
filteredItems,
};
}

+ 12
- 3
src/store/selectors/randomDataSelectors.js Zobrazit soubor

@@ -2,9 +2,8 @@ import { createSelector } from 'reselect';

const randomDataSelector = (state) => state.randomData;

export const itemsSelector = createSelector(
randomDataSelector,
(state) => state.items
export const itemsSelector = createSelector(randomDataSelector, (state) =>
(state.filter) ? state.filteredItems : state.items
);

export const pageSelector = createSelector(
@@ -21,3 +20,13 @@ export const countSelector = createSelector(
randomDataSelector,
(state) => state.count
);

export const filterSelector = createSelector(
randomDataSelector,
(state) => state.filter
);

export const sortSelector = createSelector(
randomDataSelector,
(state) => state.sort
);

Načítá se…
Zrušit
Uložit