33 * See the LICENSE file in the repository root folder for details.
44 */
55
6- import { Box , Checkbox , Chip , IconButton , Typography , useTheme } from '@mui/material' ;
7- import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore' ;
8- import UnfoldLessIcon from '@mui/icons-material/UnfoldLess' ;
9- import RestartAltIcon from '@mui/icons-material/RestartAlt' ;
10- import { ChangeEvent } from 'react' ;
6+ import {
7+ Box ,
8+ Checkbox ,
9+ Typography ,
10+ useTheme ,
11+ Accordion ,
12+ AccordionSummary ,
13+ AccordionDetails ,
14+ FormControlLabel ,
15+ IconButton
16+ } from '@mui/material' ;
17+ import ExpandMoreIcon from '@mui/icons-material/ExpandMore' ;
18+ import CloseIcon from '@mui/icons-material/Close' ;
19+ import { ChangeEvent , useState } from 'react' ;
1120
12- const FilterChipButton = ( {
13- buttonText,
14- onChange,
15- defaultChecked,
16- checked
21+ const FilterCheckboxes = ( {
22+ handlers
1723} : {
18- buttonText : string ;
19- onChange : ( event : ChangeEvent < HTMLInputElement > ) => void ;
20- defaultChecked : boolean ;
21- checked : boolean ;
22- } ) => {
23- const theme = useTheme ( ) ;
24-
25- return (
26- < Checkbox
27- onChange = { onChange }
28- sx = { {
29- '&:hover' : {
30- backgroundColor : 'transparent'
24+ handlers : { filterLabel : string ; handler : ( event : ChangeEvent < HTMLInputElement > ) => void ; defaultChecked : boolean } [ ] ;
25+ } ) => (
26+ < Box display = "flex" flexDirection = "column" >
27+ { handlers . map ( ( handler ) => (
28+ < FormControlLabel
29+ key = { handler . filterLabel }
30+ slotProps = { { typography : { fontSize : '14px' } } }
31+ control = {
32+ < Checkbox
33+ size = "small"
34+ onChange = { handler . handler }
35+ defaultChecked = { handler . defaultChecked }
36+ sx = { { padding : '2px 7px' } }
37+ />
3138 }
32- } }
33- icon = { < Chip label = { buttonText } sx = { { borderRadius : '20px' , paddingX : 1 } } /> }
34- checkedIcon = {
35- < Chip label = { buttonText } sx = { { borderRadius : '20px' , paddingX : 1 , backgroundColor : theme . palette . primary . main } } />
36- }
37- defaultChecked = { defaultChecked }
38- checked = { checked }
39- />
40- ) ;
41- } ;
39+ label = { handler . filterLabel }
40+ />
41+ ) ) }
42+ </ Box >
43+ ) ;
4244
43- const FilterRow = ( {
45+ const FilterAccordion = ( {
4446 label,
45- buttons
47+ children,
48+ expanded,
49+ onChange
4650} : {
4751 label : string ;
48- buttons : { filterLabel : string ; handler : ( event : ChangeEvent < HTMLInputElement > ) => void ; defaultChecked : boolean } [ ] ;
52+ children : React . ReactNode ;
53+ expanded : boolean ;
54+ onChange : ( ) => void ;
4955} ) => {
50- const checkedMap : { [ filterLabel : string ] : boolean } = { } ;
56+ const theme = useTheme ( ) ;
5157
52- buttons . forEach ( ( button ) => {
53- checkedMap [ button . filterLabel ] = button . defaultChecked ;
54- } ) ;
5558 return (
56- < Box width = { label === 'Team' ? '60%' : undefined } >
57- < Typography variant = "h6" component = "label" textAlign = "right" >
58- { label }
59- </ Typography >
60- < Box display = { 'flex' } flexDirection = { label === 'Team' ? undefined : 'column' } flexWrap = { 'wrap' } >
61- { buttons . map ( ( button ) => (
62- < FilterChipButton
63- buttonText = { button . filterLabel }
64- onChange = { button . handler }
65- defaultChecked = { button . defaultChecked }
66- checked = { checkedMap [ button . filterLabel ] }
67- />
68- ) ) }
69- </ Box >
70- </ Box >
59+ < Accordion
60+ disableGutters
61+ elevation = { 0 }
62+ expanded = { expanded }
63+ onChange = { onChange }
64+ sx = { {
65+ backgroundColor : 'transparent' ,
66+ '&:before' : { display : 'none' }
67+ } }
68+ >
69+ < AccordionSummary
70+ expandIcon = { < ExpandMoreIcon sx = { { color : theme . palette . text . secondary } } /> }
71+ sx = { {
72+ minHeight : '36px' ,
73+ px : 0 ,
74+ flexDirection : 'row-reverse' ,
75+ gap : 1 ,
76+ '& .MuiAccordionSummary-expandIconWrapper' : { marginRight : 0 , marginLeft : 0 } ,
77+ '& .MuiAccordionSummary-content' : { margin : '6px 0' }
78+ } }
79+ >
80+ < Typography variant = "h6" fontWeight = "normal" color = "text.primary" >
81+ { label }
82+ </ Typography >
83+ </ AccordionSummary >
84+ < AccordionDetails sx = { { padding : '0 0 0 36px' } } > { children } </ AccordionDetails >
85+ </ Accordion >
7186 ) ;
7287} ;
7388
@@ -92,88 +107,88 @@ interface GanttChartFiltersProps {
92107 resetHandler : ( ) => void ;
93108 collapseHandler : ( ) => void ;
94109 expandHandler : ( ) => void ;
110+ onClose : ( ) => void ;
95111}
96112
97113const GanttChartFilters = ( {
98114 carHandlers,
99115 teamTypeHandlers,
100116 teamHandlers,
101- overdueHandler,
102- hideTasksHandler,
103117 resetHandler,
104- collapseHandler,
105- expandHandler
118+ onClose
106119} : GanttChartFiltersProps ) => {
107- const FilterButtons = ( ) => {
108- return (
109- < Box display = { 'flex' } flexDirection = { 'column' } alignItems = { 'center' } mt = { - 1 } mb = { 1 } >
110- < IconButton onClick = { expandHandler } >
111- < UnfoldMoreIcon sx = { { color : '#ef4345' } } />
112- </ IconButton >
113- < Typography fontSize = { '10px' } sx = { { color : '#ef4345' } } >
114- Expand
115- </ Typography >
116- < IconButton onClick = { collapseHandler } >
117- < UnfoldLessIcon sx = { { color : '#ef4345' } } />
118- </ IconButton >
119- < Typography fontSize = { '10px' } sx = { { color : '#ef4345' } } >
120- Collapse
120+ const theme = useTheme ( ) ;
121+
122+ const [ expanded , setExpanded ] = useState ( {
123+ car : true ,
124+ division : true ,
125+ team : true
126+ } ) ;
127+
128+ const [ resetKey , setResetKey ] = useState ( 0 ) ;
129+
130+ const handleReset = ( ) => {
131+ setResetKey ( ( prev ) => prev + 1 ) ;
132+ resetHandler ( ) ;
133+ } ;
134+
135+ const toggle = ( section : keyof typeof expanded ) => {
136+ setExpanded ( ( prev ) => ( { ...prev , [ section ] : ! prev [ section ] } ) ) ;
137+ } ;
138+
139+ return (
140+ < Box
141+ display = "flex"
142+ flexDirection = "column"
143+ sx = { { padding : 2 , width : '20rem' , backgroundColor : theme . palette . background . paper , borderRadius : 1 } }
144+ >
145+ < Box display = "flex" flexDirection = "row" justifyContent = "space-between" alignItems = "center" sx = { { mb : 0.5 } } >
146+ < Typography variant = "h5" fontWeight = "normal" color = "text.primary" >
147+ Filters
121148 </ Typography >
122- < IconButton onClick = { resetHandler } >
123- < RestartAltIcon sx = { { color : '#ef4345' } } />
149+ < IconButton size = "small" onClick = { onClose } >
150+ < CloseIcon fontSize = "small" />
124151 </ IconButton >
125- < Typography fontSize = { '10px' } sx = { { color : '#ef4345' } } >
152+ </ Box >
153+
154+ < Box display = "flex" flexDirection = "row" alignItems = "center" gap = { 0.5 } sx = { { mb : - 0.5 } } >
155+ < Typography
156+ fontSize = "14px"
157+ sx = { { color : theme . palette . primary . main , cursor : 'pointer' , '&:hover' : { textDecoration : 'underline' } } }
158+ onClick = { handleReset }
159+ >
126160 Reset
127161 </ Typography >
128- < Checkbox
129- onChange = { overdueHandler [ 0 ] . handler }
130- sx = { {
131- '&:hover' : {
132- backgroundColor : 'transparent'
133- } ,
134- color : '#ef4345'
135- } }
136- defaultChecked = { overdueHandler [ 0 ] . defaultChecked }
137- checked = { overdueHandler [ 0 ] . defaultChecked }
138- />
139- < Typography fontSize = { '10px' } sx = { { color : '#ef4345' } } >
140- Overdue
162+ < Typography sx = { { color : '#ffffff' , lineHeight : 2.75 , fontSize : '0.5rem' } } > •</ Typography >
163+ < Typography
164+ fontSize = "13px"
165+ sx = { { color : theme . palette . primary . main , cursor : 'pointer' , '&:hover' : { textDecoration : 'underline' } } }
166+ onClick = { ( ) => setExpanded ( { car : true , division : true , team : true } ) }
167+ >
168+ Expand All
141169 </ Typography >
142- < Checkbox
143- onChange = { hideTasksHandler [ 0 ] . handler }
144- sx = { {
145- '&:hover' : {
146- backgroundColor : 'transparent'
147- } ,
148- color : '#ef4345'
149- } }
150- defaultChecked = { hideTasksHandler [ 0 ] . defaultChecked }
151- checked = { hideTasksHandler [ 0 ] . defaultChecked }
152- />
153- < Typography fontSize = { '10px' } sx = { { color : '#ef4345' } } >
154- Hide Tasks
170+ < Typography sx = { { color : '#ffffff' , lineHeight : 2.75 , fontSize : '0.5rem' } } > •</ Typography >
171+ < Typography
172+ fontSize = "13px"
173+ sx = { { color : theme . palette . primary . main , cursor : 'pointer' , '&:hover' : { textDecoration : 'underline' } } }
174+ onClick = { ( ) => setExpanded ( { car : false , division : false , team : false } ) }
175+ >
176+ Collapse All
155177 </ Typography >
156178 </ Box >
157- ) ;
158- } ;
159179
160- return (
161- < Box
162- display = { 'flex' }
163- sx = { {
164- justifyContent : 'start' ,
165- alignItems : 'start' ,
166- paddingLeft : 2 ,
167- paddingTop : 2 ,
168- maxWidth : '45rem'
169- } }
170- >
171- < FilterRow label = "Car" buttons = { carHandlers } />
172- < FilterRow label = "Subteam" buttons = { teamTypeHandlers } />
173- < FilterRow label = "Team" buttons = { teamHandlers } />
174- < FilterButtons />
180+ < FilterAccordion label = "Car" expanded = { expanded . car } onChange = { ( ) => toggle ( 'car' ) } >
181+ < FilterCheckboxes key = { `car-${ resetKey } ` } handlers = { carHandlers } />
182+ </ FilterAccordion >
183+
184+ < FilterAccordion label = "Division" expanded = { expanded . division } onChange = { ( ) => toggle ( 'division' ) } >
185+ < FilterCheckboxes key = { `division-${ resetKey } ` } handlers = { teamTypeHandlers } />
186+ </ FilterAccordion >
187+
188+ < FilterAccordion label = "Team" expanded = { expanded . team } onChange = { ( ) => toggle ( 'team' ) } >
189+ < FilterCheckboxes key = { `team-${ resetKey } ` } handlers = { teamHandlers } />
190+ </ FilterAccordion >
175191 </ Box >
176192 ) ;
177193} ;
178-
179194export default GanttChartFilters ;
0 commit comments