Revize 1c710f4f
Přidáno uživatelem Václav Honzík před téměř 3 roky(ů)
frontend/package.json | ||
---|---|---|
63 | 63 |
"@types/react-dom": "^17.0.9", |
64 | 64 |
"@types/react-redux": "^7.1.23", |
65 | 65 |
"@types/redux-persist": "^4.3.1", |
66 |
"@types/yup": "^0.29.13" |
|
66 |
"@types/yup": "^0.29.13", |
|
67 |
"redux-devtools-extension": "^2.13.9" |
|
67 | 68 |
} |
68 | 69 |
} |
frontend/src/features/Catalog/Catalog.tsx | ||
---|---|---|
1 | 1 |
import { |
2 |
Box, |
|
3 |
Button, |
|
4 |
Collapse, |
|
5 | 2 |
Container, |
6 |
Grid, |
|
7 | 3 |
Paper, |
8 |
Stack, |
|
9 |
TextField, |
|
10 | 4 |
Typography, |
11 | 5 |
} from '@mui/material' |
12 | 6 |
import CatalogTable from './CatalogTable' |
13 |
import { Fragment, useState } from 'react' |
|
7 |
import { Fragment } from 'react' |
|
8 |
import CatalogFilter from './CatalogFilter' |
|
14 | 9 |
|
15 | 10 |
const Catalog = () => { |
16 |
const [filterOpen, setFilterOpen] = useState(false) |
|
17 |
const toggleFilter = () => { |
|
18 |
setFilterOpen(!filterOpen) |
|
19 |
} |
|
11 |
|
|
20 | 12 |
|
21 | 13 |
return ( |
22 | 14 |
<Fragment> |
... | ... | |
27 | 19 |
> |
28 | 20 |
<Container sx={{ mt: 4 }}> |
29 | 21 |
<Typography variant="h3" sx={{mb: 2}} fontWeight="bold" >Catalog</Typography> |
30 |
<Button variant="outlined" color="primary" onClick={toggleFilter}> |
|
31 |
Filter |
|
32 |
</Button> |
|
33 |
<Collapse in={filterOpen} timeout="auto" unmountOnExit> |
|
34 |
<Grid container spacing={1} alignItems="stretch"> |
|
35 |
<Grid item xs={6}> |
|
36 |
<Stack |
|
37 |
direction="column" |
|
38 |
spacing={1} |
|
39 |
sx={{ mt: 2 }} |
|
40 |
> |
|
41 |
<Stack direction="row" spacing={2}> |
|
42 |
<TextField |
|
43 |
size="small" |
|
44 |
id="name" |
|
45 |
label="Name" |
|
46 |
/> |
|
47 |
<TextField |
|
48 |
size="small" |
|
49 |
id="type" |
|
50 |
label="Type" |
|
51 |
/> |
|
52 |
</Stack> |
|
53 |
<Stack direction="row" spacing={2}> |
|
54 |
<TextField |
|
55 |
size="small" |
|
56 |
id="writtenForm" |
|
57 |
label="Written form" |
|
58 |
/> |
|
59 |
<TextField |
|
60 |
size="small" |
|
61 |
id="stateOrTerritory" |
|
62 |
label="State or territory" |
|
63 |
/> |
|
64 |
<TextField |
|
65 |
size="small" |
|
66 |
id="groupBy" |
|
67 |
label="Group by" |
|
68 |
/> |
|
69 |
</Stack> |
|
70 |
</Stack> |
|
71 |
</Grid> |
|
72 |
<Grid item xs sx={{ mt: 'auto', ml: 1, mb: 1 }}> |
|
73 |
<Stack |
|
74 |
direction="row" |
|
75 |
justifyContent="flex-start" |
|
76 |
alignItems="flex-end" |
|
77 |
> |
|
78 |
<Button variant="outlined">Search</Button> |
|
79 |
</Stack> |
|
80 |
</Grid> |
|
81 |
</Grid> |
|
82 |
</Collapse> |
|
83 |
|
|
84 |
<Box sx={{ mt: 4 }}> |
|
22 |
<CatalogFilter /> |
|
85 | 23 |
<CatalogTable /> |
86 |
</Box> |
|
87 | 24 |
</Container> |
88 | 25 |
</Paper> |
89 | 26 |
</Fragment> |
frontend/src/features/Catalog/CatalogFilter.tsx | ||
---|---|---|
1 |
import { Button, Collapse, Grid, Stack, TextField } from '@mui/material' |
|
2 |
import { Fragment, useState } from 'react' |
|
3 |
import { useDispatch } from 'react-redux' |
|
4 |
import { setFilter, CatalogFilter as Filter } from './catalogSlice' |
|
5 |
import { fetchItems } from './catalogThunks' |
|
6 |
|
|
7 |
const CatalogFilter = () => { |
|
8 |
const dispatch = useDispatch() |
|
9 |
|
|
10 |
const [filterOpen, setFilterOpen] = useState(false) |
|
11 |
const toggleFilter = () => { |
|
12 |
setFilterOpen(!filterOpen) |
|
13 |
} |
|
14 |
|
|
15 |
// current filter object |
|
16 |
const filter: Filter = {} |
|
17 |
const applyFilter = () => { |
|
18 |
dispatch(fetchItems()) |
|
19 |
} |
|
20 |
|
|
21 |
|
|
22 |
return ( |
|
23 |
<Fragment> |
|
24 |
<Button variant="outlined" color="primary" onClick={toggleFilter}> |
|
25 |
Filter |
|
26 |
</Button> |
|
27 |
<Collapse in={filterOpen} timeout="auto" unmountOnExit> |
|
28 |
<Grid container spacing={1} alignItems="stretch"> |
|
29 |
<Grid item xs={6}> |
|
30 |
<Stack direction="column" spacing={1} sx={{ mt: 2 }}> |
|
31 |
<Stack direction="row" spacing={2}> |
|
32 |
<TextField |
|
33 |
size="small" |
|
34 |
id="name" |
|
35 |
label="Name" |
|
36 |
onChange={(e: any) => { |
|
37 |
filter.name = e.target.value |
|
38 |
dispatch(setFilter(filter)) |
|
39 |
}} |
|
40 |
/> |
|
41 |
<TextField |
|
42 |
size="small" |
|
43 |
id="type" |
|
44 |
label="Type" |
|
45 |
onChange={(e: any) => { |
|
46 |
filter.type = e.target.value |
|
47 |
dispatch(setFilter(filter)) |
|
48 |
}} |
|
49 |
/> |
|
50 |
</Stack> |
|
51 |
<Stack direction="row" spacing={2}> |
|
52 |
<TextField |
|
53 |
size="small" |
|
54 |
id="writtenForm" |
|
55 |
label="Written form" |
|
56 |
/> |
|
57 |
<TextField |
|
58 |
size="small" |
|
59 |
id="stateOrTerritory" |
|
60 |
label="State or territory" |
|
61 |
onChange={(e: any) => { |
|
62 |
filter.country = e.target.value |
|
63 |
dispatch(setFilter(filter)) |
|
64 |
}} |
|
65 |
/> |
|
66 |
<TextField |
|
67 |
size="small" |
|
68 |
id="groupBy" |
|
69 |
label="Group by" |
|
70 |
/> |
|
71 |
</Stack> |
|
72 |
</Stack> |
|
73 |
</Grid> |
|
74 |
<Grid item xs sx={{ mt: 'auto', ml: 1, mb: 1 }}> |
|
75 |
<Stack |
|
76 |
direction="row" |
|
77 |
justifyContent="flex-start" |
|
78 |
alignItems="flex-end" |
|
79 |
> |
|
80 |
<Button variant="outlined" onClick={applyFilter}>Search</Button> |
|
81 |
</Stack> |
|
82 |
</Grid> |
|
83 |
</Grid> |
|
84 |
</Collapse> |
|
85 |
</Fragment> |
|
86 |
) |
|
87 |
} |
|
88 |
|
|
89 |
export default CatalogFilter |
frontend/src/features/Catalog/catalogSlice.tsx | ||
---|---|---|
26 | 26 |
name: 'catalog', |
27 | 27 |
initialState, |
28 | 28 |
reducers: { |
29 |
setCatalogFilter: (state, action) => ({
|
|
29 |
setFilter: (state, action) => ({ |
|
30 | 30 |
...state, |
31 |
catalogFilter: action.payload.catalogFilter,
|
|
31 |
filter: {...action.payload},
|
|
32 | 32 |
}), |
33 | 33 |
clearFilter: (state, action) => ({ |
34 | 34 |
...state, |
35 | 35 |
loading: true, |
36 |
catalogFilter: {},
|
|
36 |
filter: {},
|
|
37 | 37 |
}), |
38 | 38 |
clear: (state) => ({ ...initialState }), |
39 | 39 |
setLoading: (state) => ({ ...state, loading: true }), |
... | ... | |
57 | 57 |
}, |
58 | 58 |
}) |
59 | 59 |
|
60 |
export const { setCatalogFilter, clearFilter, clear, setLoading, consumeError } = catalogSlice.actions
|
|
60 |
export const { setFilter, clearFilter, clear, setLoading, consumeError } = catalogSlice.actions |
|
61 | 61 |
const reducer = catalogSlice.reducer |
62 | 62 |
export default reducer |
frontend/src/features/redux/store.ts | ||
---|---|---|
1 |
|
|
2 | 1 |
import { applyMiddleware, combineReducers, createStore } from 'redux' |
3 | 2 |
import { persistStore } from 'redux-persist' |
4 | 3 |
import thunk from 'redux-thunk' |
5 | 4 |
import userReducer from '../Auth/userSlice' |
6 | 5 |
import themeReducer from '../Theme/themeReducer' |
7 | 6 |
import catalogReducer from '../Catalog/catalogSlice' |
7 |
import { composeWithDevTools } from 'redux-devtools-extension' |
|
8 | 8 |
|
9 |
const composeEnhancers = composeWithDevTools({}) |
|
9 | 10 |
|
10 | 11 |
// Store holds shared state in the application |
11 | 12 |
const store = createStore( |
12 |
combineReducers({ user: userReducer, theme: themeReducer, catalog: catalogReducer }), |
|
13 |
applyMiddleware(thunk) // Thunk middleware so we can async fetch data from the api |
|
13 |
combineReducers({ |
|
14 |
user: userReducer, |
|
15 |
theme: themeReducer, |
|
16 |
catalog: catalogReducer, |
|
17 |
}), |
|
18 |
process.env.REACT_APP_DEV_ENV === 'true' |
|
19 |
? composeEnhancers( |
|
20 |
applyMiddleware(thunk) // Thunk middleware so we can async fetch data from the api |
|
21 |
) |
|
22 |
: applyMiddleware(thunk) |
|
14 | 23 |
) |
15 | 24 |
|
16 | 25 |
export default store |
frontend/src/index.tsx | ||
---|---|---|
15 | 15 |
ReactDOM.render( |
16 | 16 |
<Provider store={store}> |
17 | 17 |
<PersistGate loading={null} persistor={persistor}> |
18 |
<React.StrictMode>
|
|
18 |
{/* <React.StrictMode> */}
|
|
19 | 19 |
<BrowserRouter> |
20 | 20 |
<App /> |
21 | 21 |
</BrowserRouter> |
22 |
</React.StrictMode>
|
|
22 |
{/* </React.StrictMode> */}
|
|
23 | 23 |
</PersistGate> |
24 | 24 |
</Provider>, |
25 | 25 |
document.getElementById('root') |
frontend/yarn.lock | ||
---|---|---|
7759 | 7759 |
indent-string "^4.0.0" |
7760 | 7760 |
strip-indent "^3.0.0" |
7761 | 7761 |
|
7762 |
redux-devtools-extension@^2.13.9: |
|
7763 |
version "2.13.9" |
|
7764 |
resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.9.tgz#6b764e8028b507adcb75a1cae790f71e6be08ae7" |
|
7765 |
integrity sha512-cNJ8Q/EtjhQaZ71c8I9+BPySIBVEKssbPpskBfsXqb8HJ002A3KRVHfeRzwRo6mGPqsm7XuHTqNSNeS1Khig0A== |
|
7766 |
|
|
7762 | 7767 |
redux-persist@*, redux-persist@^6.0.0: |
7763 | 7768 |
version "6.0.0" |
7764 | 7769 |
resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-6.0.0.tgz#b4d2972f9859597c130d40d4b146fecdab51b3a8" |
Také k dispozici: Unified diff
filter functional
re #9545