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' ;
11-
12- const FilterChipButton = ( {
13- buttonText,
14- onChange,
15- defaultChecked,
16- checked
17- } : {
18- buttonText : string ;
19- onChange : ( event : ChangeEvent < HTMLInputElement > ) => void ;
20- defaultChecked : boolean ;
21- checked : boolean ;
22- } ) => {
23- const theme = useTheme ( ) ;
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' ;
2420
25- return (
26- < Checkbox
27- onChange = { onChange }
28- sx = { {
29- '&:hover' : {
30- backgroundColor : 'transparent'
21+ const FilterCheckboxes = ( {
22+ handlers
23+ } : {
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
@@ -79,99 +94,88 @@ interface GanttChartFiltersProps {
7994 defaultChecked : boolean ;
8095 } [ ] ;
8196 teamHandlers : { filterLabel : string ; handler : ( event : ChangeEvent < HTMLInputElement > ) => void ; defaultChecked : boolean } [ ] ;
82- overdueHandler : {
83- filterLabel : string ;
84- handler : ( event : ChangeEvent < HTMLInputElement > ) => void ;
85- defaultChecked ?: boolean ;
86- } [ ] ;
87- hideTasksHandler : {
88- filterLabel : string ;
89- handler : ( event : ChangeEvent < HTMLInputElement > ) => void ;
90- defaultChecked ?: boolean ;
91- } [ ] ;
9297 resetHandler : ( ) => void ;
93- collapseHandler : ( ) => void ;
94- expandHandler : ( ) => void ;
98+ onClose : ( ) => void ;
9599}
96100
97101const GanttChartFilters = ( {
98102 carHandlers,
99103 teamTypeHandlers,
100104 teamHandlers,
101- overdueHandler,
102- hideTasksHandler,
103105 resetHandler,
104- collapseHandler,
105- expandHandler
106+ onClose
106107} : 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
108+ const theme = useTheme ( ) ;
109+
110+ const [ expanded , setExpanded ] = useState ( {
111+ car : true ,
112+ division : true ,
113+ team : true
114+ } ) ;
115+
116+ const [ resetKey , setResetKey ] = useState ( 0 ) ;
117+
118+ const handleReset = ( ) => {
119+ setResetKey ( ( prev ) => prev + 1 ) ;
120+ resetHandler ( ) ;
121+ } ;
122+
123+ const toggle = ( section : keyof typeof expanded ) => {
124+ setExpanded ( ( prev ) => ( { ...prev , [ section ] : ! prev [ section ] } ) ) ;
125+ } ;
126+
127+ return (
128+ < Box
129+ display = "flex"
130+ flexDirection = "column"
131+ sx = { { padding : 2 , width : '20rem' , backgroundColor : theme . palette . background . paper , borderRadius : 1 } }
132+ >
133+ < Box display = "flex" flexDirection = "row" justifyContent = "space-between" alignItems = "center" sx = { { mb : 0.5 } } >
134+ < Typography variant = "h5" fontWeight = "normal" color = "text.primary" >
135+ Filters
121136 </ Typography >
122- < IconButton onClick = { resetHandler } >
123- < RestartAltIcon sx = { { color : '#ef4345' } } />
137+ < IconButton size = "small" onClick = { onClose } >
138+ < CloseIcon fontSize = "small" />
124139 </ IconButton >
125- < Typography fontSize = { '10px' } sx = { { color : '#ef4345' } } >
140+ </ Box >
141+
142+ < Box display = "flex" flexDirection = "row" alignItems = "center" gap = { 0.5 } sx = { { mb : - 0.5 } } >
143+ < Typography
144+ fontSize = "14px"
145+ sx = { { color : theme . palette . primary . main , cursor : 'pointer' , '&:hover' : { textDecoration : 'underline' } } }
146+ onClick = { handleReset }
147+ >
126148 Reset
127149 </ 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
150+ < Typography sx = { { color : theme . palette . text . primary , lineHeight : 2.75 , fontSize : '0.5rem' } } > •</ Typography >
151+ < Typography
152+ fontSize = "13px"
153+ sx = { { color : theme . palette . primary . main , cursor : 'pointer' , '&:hover' : { textDecoration : 'underline' } } }
154+ onClick = { ( ) => setExpanded ( { car : true , division : true , team : true } ) }
155+ >
156+ Expand All
141157 </ 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
158+ < Typography sx = { { color : theme . palette . text . primary , lineHeight : 2.75 , fontSize : '0.5rem' } } > •</ Typography >
159+ < Typography
160+ fontSize = "13px"
161+ sx = { { color : theme . palette . primary . main , cursor : 'pointer' , '&:hover' : { textDecoration : 'underline' } } }
162+ onClick = { ( ) => setExpanded ( { car : false , division : false , team : false } ) }
163+ >
164+ Collapse All
155165 </ Typography >
156166 </ Box >
157- ) ;
158- } ;
159167
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 />
168+ < FilterAccordion label = "Car" expanded = { expanded . car } onChange = { ( ) => toggle ( 'car' ) } >
169+ < FilterCheckboxes key = { `car-${ resetKey } ` } handlers = { carHandlers } />
170+ </ FilterAccordion >
171+
172+ < FilterAccordion label = "Division" expanded = { expanded . division } onChange = { ( ) => toggle ( 'division' ) } >
173+ < FilterCheckboxes key = { `division-${ resetKey } ` } handlers = { teamTypeHandlers } />
174+ </ FilterAccordion >
175+
176+ < FilterAccordion label = "Team" expanded = { expanded . team } onChange = { ( ) => toggle ( 'team' ) } >
177+ < FilterCheckboxes key = { `team-${ resetKey } ` } handlers = { teamHandlers } />
178+ </ FilterAccordion >
175179 </ Box >
176180 ) ;
177181} ;
0 commit comments