1
- import React from "react" ;
1
+ import React , { useState } from "react" ;
2
2
import { styled } from "@mui/material/styles" ;
3
3
import { format as formatDate } from "date-fns" ;
4
4
import { Popover , Chip , useTheme , Drawer , Button , useMediaQuery , colors } from "@mui/material" ;
5
5
import { ArrowDropDown as ArrowDropDownIcon , Cancel as CancelIcon } from "@mui/icons-material" ;
6
- import InfiniteCalendar , { Calendar , withRange } from "react-infinite -calendar" ;
6
+ import Calendar from "react-calendar" ;
7
7
8
- import "react-infinite- calendar/styles .css" ;
9
- import { TransactionDateRangePayload } from "../models" ;
10
- import { hasDateQueryFields } from "../utils/transactionUtils" ;
8
+ import "react-calendar/dist/Calendar .css" ;
9
+ import { TransactionDateRangePayload , Value , ValuePiece } from "../models" ;
10
+ import { hasDateQueryFields , localDateToUTCISOString } from "../utils/transactionUtils" ;
11
11
12
12
const PREFIX = "TransactionListDateRangeFilter" ;
13
13
@@ -27,7 +27,6 @@ const Root = styled("div")(({ theme }) => ({
27
27
} ) ) ;
28
28
29
29
const { indigo } = colors ;
30
- const CalendarWithRange = withRange ( Calendar ) ;
31
30
32
31
export type TransactionListDateRangeFilterProps = {
33
32
filterDateRange : Function ;
@@ -43,15 +42,19 @@ const TransactionListDateRangeFilter: React.FC<TransactionListDateRangeFilterPro
43
42
const theme = useTheme ( ) ;
44
43
const xsBreakpoint = useMediaQuery ( theme . breakpoints . only ( "xs" ) ) ;
45
44
const queryHasDateFields = dateRangeFilters && hasDateQueryFields ( dateRangeFilters ) ;
45
+ const [ calendarValue , setCalendarValue ] = useState < Value > ( null ) ;
46
46
47
47
const [ dateRangeAnchorEl , setDateRangeAnchorEl ] = React . useState < HTMLDivElement | null > ( null ) ;
48
48
49
- const onCalendarSelect = ( e : { eventType : number ; start : any ; end : any } ) => {
50
- if ( e . eventType === 3 ) {
51
- filterDateRange ( {
52
- dateRangeStart : new Date ( e . start . setUTCHours ( 0 , 0 , 0 , 0 ) ) . toISOString ( ) ,
53
- dateRangeEnd : new Date ( e . end . setUTCHours ( 23 , 59 , 59 , 999 ) ) . toISOString ( ) ,
54
- } ) ;
49
+ const onCalendarSelect = ( val : Value ) => {
50
+ if ( val && ! ( val instanceof Date ) ) {
51
+ const [ rangeStart , rangeEnd ] = val ;
52
+ const calValue = {
53
+ dateRangeStart : localDateToUTCISOString ( rangeStart ) ,
54
+ dateRangeEnd : localDateToUTCISOString ( rangeEnd ) ,
55
+ } ;
56
+ setCalendarValue ( val ) ;
57
+ filterDateRange ( calValue ) ;
55
58
setDateRangeAnchorEl ( null ) ;
56
59
}
57
60
} ;
@@ -67,13 +70,16 @@ const TransactionListDateRangeFilter: React.FC<TransactionListDateRangeFilterPro
67
70
const dateRangeOpen = Boolean ( dateRangeAnchorEl ) ;
68
71
const dateRangeId = dateRangeOpen ? "date-range-popover" : undefined ;
69
72
70
- const formatButtonDate = ( date : string ) => {
71
- return formatDate ( new Date ( date ) , "MMM, d yyyy" ) ;
73
+ const formatButtonDate = ( date : Date ) => {
74
+ return formatDate ( date , "MMM, d yyyy" ) ;
72
75
} ;
73
76
74
- const dateRangeLabel = ( dateRangeFields : TransactionDateRangePayload ) => {
75
- const { dateRangeStart, dateRangeEnd } = dateRangeFields ;
76
- return `${ formatButtonDate ( dateRangeStart ! ) } - ${ formatButtonDate ( dateRangeEnd ! ) } ` ;
77
+ const dateRangeLabel = ( dateRangeFields : Value ) => {
78
+ if ( dateRangeFields && ! ( dateRangeFields instanceof Date ) ) {
79
+ const [ dateRangeStart , dateRangeEnd ] = dateRangeFields ;
80
+ const label = `${ formatButtonDate ( dateRangeStart ! ) } - ${ formatButtonDate ( dateRangeEnd ! ) } ` ;
81
+ return label ;
82
+ }
77
83
} ;
78
84
79
85
return (
@@ -95,9 +101,10 @@ const TransactionListDateRangeFilter: React.FC<TransactionListDateRangeFilterPro
95
101
variant = "outlined"
96
102
onClick = { handleDateRangeClick }
97
103
data-test = "transaction-list-filter-date-range-button"
98
- label = { `Date: ${ dateRangeLabel ( dateRangeFilters ) } ` }
104
+ label = { `Date: ${ dateRangeLabel ( calendarValue ) } ` }
99
105
deleteIcon = { < CancelIcon data-test = "transaction-list-filter-date-clear-button" /> }
100
106
onDelete = { ( ) => {
107
+ setCalendarValue ( null ) ;
101
108
resetDateRange ( ) ;
102
109
} }
103
110
/>
@@ -118,28 +125,12 @@ const TransactionListDateRangeFilter: React.FC<TransactionListDateRangeFilterPro
118
125
} }
119
126
className = { classes . popover }
120
127
>
121
- < InfiniteCalendar
122
- data-test = "transaction-list-filter-date-range"
123
- width = { xsBreakpoint ? window . innerWidth : 350 }
124
- height = { xsBreakpoint ? window . innerHeight : 300 }
125
- rowHeight = { 50 }
126
- Component = { CalendarWithRange }
127
- selected = { false }
128
- onSelect = { onCalendarSelect }
129
- locale = { {
130
- headerFormat : "MMM Do" ,
131
- } }
132
- theme = { {
133
- accentColor : indigo [ "400" ] ,
134
- headerColor : indigo [ "500" ] ,
135
- weekdayColor : indigo [ "300" ] ,
136
- selectionColor : indigo [ "300" ] ,
137
- floatingNav : {
138
- background : indigo [ "400" ] ,
139
- color : "#FFF" ,
140
- chevron : "#FFA726" ,
141
- } ,
142
- } }
128
+ < RangeCalendar
129
+ onCalendarSelect = { onCalendarSelect }
130
+ xsBreakpoint = { xsBreakpoint }
131
+ color = { indigo }
132
+ dataTest = "transaction-list-filter-date-range"
133
+ defaultValue = { calendarValue }
143
134
/>
144
135
</ Popover >
145
136
) }
@@ -154,33 +145,56 @@ const TransactionListDateRangeFilter: React.FC<TransactionListDateRangeFilterPro
154
145
< Button data-test = "date-range-filter-drawer-close" onClick = { ( ) => handleDateRangeClose ( ) } >
155
146
Close
156
147
</ Button >
157
- < InfiniteCalendar
158
- data-test = "transaction-list-filter-date-range"
159
- width = { window . innerWidth }
160
- height = { window . innerHeight - 185 }
161
- rowHeight = { 50 }
162
- Component = { CalendarWithRange }
163
- selected = { false }
164
- onSelect = { onCalendarSelect }
165
- locale = { {
166
- headerFormat : "MMM Do" ,
167
- } }
168
- theme = { {
169
- accentColor : indigo [ "400" ] ,
170
- headerColor : indigo [ "500" ] ,
171
- weekdayColor : indigo [ "300" ] ,
172
- selectionColor : indigo [ "300" ] ,
173
- floatingNav : {
174
- background : indigo [ "400" ] ,
175
- color : "#FFF" ,
176
- chevron : "#FFA726" ,
177
- } ,
178
- } }
148
+ < RangeCalendar
149
+ onCalendarSelect = { onCalendarSelect }
150
+ xsBreakpoint = { xsBreakpoint }
151
+ color = { indigo }
152
+ dataTest = "transaction-list-filter-date-range"
153
+ defaultValue = { calendarValue }
179
154
/>
180
155
</ Drawer >
181
156
) }
182
157
</ Root >
183
158
) ;
184
159
} ;
185
160
161
+ export function RangeCalendar ( {
162
+ onCalendarSelect,
163
+ xsBreakpoint,
164
+ color,
165
+ dataTest,
166
+ defaultValue,
167
+ } : {
168
+ onCalendarSelect : ( value : Value ) => void ;
169
+ xsBreakpoint : boolean ;
170
+ color : Record < string , string > ;
171
+ dataTest : string ;
172
+ defaultValue : Value ;
173
+ } ) {
174
+ const [ value , setValue ] = useState < Value > ( defaultValue ) ;
175
+
176
+ const width = xsBreakpoint ? window . innerWidth : 350 ;
177
+ const height = xsBreakpoint ? window . innerHeight : 300 ;
178
+
179
+ const handleChange = ( val : Value , _ : any ) => {
180
+ setValue ( val ) ;
181
+ onCalendarSelect ( val ) ;
182
+ } ;
183
+
184
+ return (
185
+ < div
186
+ data-test = { dataTest }
187
+ style = { {
188
+ width,
189
+ maxWidth : "100%" ,
190
+ background : color [ "400" ] ,
191
+ padding : 8 ,
192
+ borderRadius : 8 ,
193
+ } }
194
+ >
195
+ < Calendar onChange = { handleChange } value = { value } selectRange = { true } />
196
+ </ div >
197
+ ) ;
198
+ }
199
+
186
200
export default TransactionListDateRangeFilter ;
0 commit comments