1+ import { Drawer , useMediaQuery } from '@mui/material' ;
12import { SelectChangeEvent } from '@mui/material/Select' ;
23import React from 'react' ;
34import { Button } from '../base/Button' ;
@@ -37,11 +38,23 @@ function UniversalFilter({
3738} : UniversalFilterProps ) : JSX . Element {
3839 const [ anchorEl , setAnchorEl ] = React . useState < null | HTMLElement > ( null ) ;
3940 const [ open , setOpen ] = React . useState ( false ) ;
41+
4042 const theme = useTheme ( ) ;
43+ const muiTheme = useTheme ( ) ;
44+ const isMobile = useMediaQuery ( muiTheme . breakpoints . down ( 'sm' ) ) ;
45+
46+ const handleClick = ( event : React . MouseEvent < HTMLElement > ) => {
47+ setAnchorEl ( event . currentTarget ) ;
48+ setOpen ( ( prevOpen ) => ! prevOpen ) ;
49+ } ;
50+
51+ const handleClose = ( ) => {
52+ setAnchorEl ( null ) ;
53+ setOpen ( false ) ;
54+ } ;
4155
4256 const handleFilterChange = ( event : React . ChangeEvent < { value : string } > , columnName : string ) => {
4357 const value = event . target . value ;
44-
4558 setSelectedFilters ( ( prevFilters ) => ( {
4659 ...prevFilters ,
4760 [ columnName ] : value
@@ -53,98 +66,91 @@ function UniversalFilter({
5366 handleApplyFilter ( ) ;
5467 } ;
5568
56- const handleClick = ( event : React . MouseEvent < HTMLElement > ) => {
57- setAnchorEl ( event . currentTarget ) ;
58- setOpen ( ( previousOpen ) => ! previousOpen ) ;
59- } ;
60-
61- const canBeOpen = open && Boolean ( anchorEl ) ;
62- const idx = canBeOpen ? 'transition-popper' : undefined ;
69+ const renderFilterContent = ( ) => (
70+ < div style = { { padding : '1rem' , width : isMobile ? '90vw' : 'auto' } } >
71+ < h3 > Filters: </ h3 >
72+ { Object . keys ( filters ) . map ( ( filterColumn ) => {
73+ const options = filters [ filterColumn ] . options ;
74+ return (
75+ < div key = { filterColumn } role = "presentation" >
76+ < InputLabel id = { filters [ filterColumn ] . name } > { filters [ filterColumn ] . name } </ InputLabel >
77+ < Select
78+ defaultValue = "All"
79+ key = { filterColumn }
80+ value = { selectedFilters [ filterColumn ] }
81+ variant = { variant }
82+ onChange = { ( e : SelectChangeEvent < unknown > ) =>
83+ handleFilterChange ( e as React . ChangeEvent < { value : string } > , filterColumn )
84+ }
85+ style = { {
86+ width : '20rem' ,
87+ marginBottom : '1rem'
88+ } }
89+ inputProps = { { 'aria-label' : 'Without label' } }
90+ displayEmpty
91+ >
92+ { showAllOption && < MenuItem value = "All" > All</ MenuItem > }
93+ { options . map ( ( option ) => (
94+ < MenuItem key = { option . value } value = { option . value } >
95+ { option . label }
96+ </ MenuItem >
97+ ) ) }
98+ </ Select >
99+ </ div >
100+ ) ;
101+ } ) }
63102
64- const handleClose = ( ) => {
65- setAnchorEl ( null ) ;
66- setOpen ( false ) ;
67- } ;
103+ < div style = { { display : 'flex' , justifyContent : 'center' } } >
104+ < Button variant = "contained" onClick = { handleApplyOnClick } >
105+ Apply
106+ </ Button >
107+ </ div >
108+ </ div >
109+ ) ;
68110
69111 return (
70- < React . Fragment >
112+ < >
71113 < div id = { id } >
72114 < TooltipIcon
73115 title = "Filter"
74116 onClick = { handleClick }
75117 icon = { < FilterIcon fill = { theme . palette . icon . default } /> }
76118 arrow
77119 />
78- < PopperListener
79- id = { idx }
80- open = { open }
81- anchorEl = { anchorEl }
82- placement = "bottom-end"
83- // transition
84- >
85- < div >
86- < ClickAwayListener
87- onClickAway = { handleClose }
88- mouseEvent = "onMouseDown"
89- touchEvent = "onTouchStart"
90- >
91- < div >
92- < Paper
93- sx = { {
94- padding : '1rem' ,
95- paddingTop : '1.8rem' ,
96- boxShadow : '0px 4px 8px rgba(0, 0, 0, 0.1)' ,
97- backgroundColor : theme . palette . background . surfaces
98- } }
99- >
100- { Object . keys ( filters ) . map ( ( filterColumn ) => {
101- const options = filters [ filterColumn ] . options ;
102- return (
103- < div key = { filterColumn } role = "presentation" >
104- < InputLabel id = { filters [ filterColumn ] . name } >
105- { filters [ filterColumn ] . name }
106- </ InputLabel >
107- < Select
108- defaultValue = "All"
109- key = { filterColumn }
110- value = { selectedFilters [ filterColumn ] }
111- variant = { variant }
112- onChange = { ( e : SelectChangeEvent < unknown > ) =>
113- handleFilterChange (
114- e as React . ChangeEvent < { value : string } > ,
115- filterColumn
116- )
117- }
118- style = { {
119- width : '15rem' ,
120- marginBottom : '1rem'
121- } }
122- inputProps = { { 'aria-label' : 'Without label' } }
123- displayEmpty
124- >
125- { showAllOption && < MenuItem value = "All" > All</ MenuItem > }
126- { options . map ( ( option ) => (
127- < MenuItem key = { option . value } value = { option . value } >
128- { option . label }
129- </ MenuItem >
130- ) ) }
131- </ Select >
132- </ div >
133- ) ;
134- } ) }
135-
136- < div style = { { display : 'flex' , justifyContent : 'flex-end' } } >
137- < Button variant = "contained" onClick = { handleApplyOnClick } >
138- Apply
139- </ Button >
140- </ div >
141- </ Paper >
142- </ div >
120+ { ! isMobile ? (
121+ < PopperListener
122+ id = { open && anchorEl ? 'transition-popper' : undefined }
123+ open = { open }
124+ anchorEl = { anchorEl }
125+ placement = "bottom-end"
126+ >
127+ < ClickAwayListener onClickAway = { handleClose } >
128+ < Paper
129+ sx = { {
130+ padding : '1rem' ,
131+ paddingTop : '1.8rem' ,
132+ boxShadow : '0px 4px 8px rgba(0, 0, 0, 0.1)' ,
133+ backgroundColor : theme . palette . background . surfaces
134+ } }
135+ >
136+ { renderFilterContent ( ) }
137+ </ Paper >
143138 </ ClickAwayListener >
144- </ div >
145- </ PopperListener >
139+ </ PopperListener >
140+ ) : (
141+ < Drawer
142+ anchor = "bottom"
143+ open = { open }
144+ onClose = { handleClose }
145+ PaperProps = { {
146+ style : { borderTopLeftRadius : '1rem' , borderTopRightRadius : '1rem' }
147+ } }
148+ >
149+ { renderFilterContent ( ) }
150+ </ Drawer >
151+ ) }
146152 </ div >
147- </ React . Fragment >
153+ </ >
148154 ) ;
149155}
150156export default UniversalFilter ;
0 commit comments