@@ -6,8 +6,11 @@ import {
6
6
Center ,
7
7
Divider ,
8
8
Flex ,
9
+ FormControl ,
10
+ FormLabel ,
9
11
HStack ,
10
12
Heading ,
13
+ Input ,
11
14
Popover ,
12
15
PopoverArrow ,
13
16
PopoverBody ,
@@ -29,12 +32,14 @@ import {
29
32
import { useTranslation } from "react-i18next" ;
30
33
import dayjs from "dayjs" ;
31
34
import { QuestionOutlineIcon , Search2Icon } from "@chakra-ui/icons" ;
32
- import { forwardRef } from "react" ;
35
+ import { forwardRef , useEffect , useState } from "react" ;
33
36
import { useUserFeedRequestsWithPagination } from "../../../hooks" ;
34
37
import { UserFeedRequestStatus } from "../../../types" ;
35
38
import { InlineErrorAlert } from "../../../../../components" ;
36
39
import { useUserFeedContext } from "../../../../../contexts/UserFeedContext" ;
37
40
import { RequestDetails } from "./RequestDetails" ;
41
+ import { GetUserFeedRequestsInput } from "../../../api" ;
42
+ import { DismissableAlert } from "../../../../../components/DismissableAlert" ;
38
43
39
44
const QuestionOutlineComponent = forwardRef < any > ( ( props , ref ) => (
40
45
< QuestionOutlineIcon fontSize = { 12 } tabIndex = { - 1 } ref = { ref } aria-hidden { ...props } />
@@ -84,16 +89,95 @@ export const RequestHistory = () => {
84
89
const {
85
90
userFeed : { id : feedId } ,
86
91
} = useUserFeedContext ( ) ;
92
+ const [ startDate , setStartDate ] = useState < string > ( ) ;
93
+ const [ endDate , setEndDate ] = useState < string > ( ) ;
94
+ const [ requestData , setRequestData ] = useState < Partial < GetUserFeedRequestsInput [ "data" ] > > ( { } ) ;
87
95
const { data, status, error, skip, nextPage, prevPage, fetchStatus, limit } =
88
96
useUserFeedRequestsWithPagination ( {
89
97
feedId,
90
- data : { } ,
98
+ data : requestData ,
91
99
} ) ;
100
+ const [ isInvalidDateRange , setIsInvalidDateRange ] = useState ( false ) ;
92
101
const { t } = useTranslation ( ) ;
93
102
94
103
const onFirstPage = skip === 0 ;
95
104
const hasNoData = data ?. result . requests . length === 0 && skip === 0 ;
96
105
106
+ useEffect ( ( ) => {
107
+ setIsInvalidDateRange ( false ) ;
108
+ } , [ fetchStatus ] ) ;
109
+
110
+ const onApplyDateRange = ( ) => {
111
+ if ( fetchStatus === "fetching" ) {
112
+ return ;
113
+ }
114
+
115
+ if ( startDate && endDate && new Date ( startDate ) > new Date ( endDate ) ) {
116
+ setIsInvalidDateRange ( true ) ;
117
+ } else {
118
+ const newDateRange = {
119
+ ...requestData ,
120
+ afterDate : startDate ? new Date ( startDate ) . toISOString ( ) : undefined ,
121
+ beforeDate : endDate ? new Date ( endDate ) . toISOString ( ) : undefined ,
122
+ } ;
123
+ setRequestData ( newDateRange ) ;
124
+ setIsInvalidDateRange ( false ) ;
125
+ }
126
+ } ;
127
+
128
+ const dateRangeForm = (
129
+ < Stack
130
+ as = "form"
131
+ onSubmit = { ( e ) => {
132
+ e . preventDefault ( ) ;
133
+ onApplyDateRange ( ) ;
134
+ } }
135
+ >
136
+ < HStack flexWrap = "wrap" >
137
+ < FormControl flex = { 1 } >
138
+ < FormLabel > Start Date Range</ FormLabel >
139
+ < Input
140
+ bg = "gray.900"
141
+ type = "datetime-local"
142
+ size = "sm"
143
+ onChange = { ( e ) => {
144
+ setStartDate ( e . target . value ) ;
145
+ } }
146
+ />
147
+ </ FormControl >
148
+ < FormControl flex = { 1 } >
149
+ < FormLabel > End Date Range</ FormLabel >
150
+ < Input
151
+ bg = "gray.900"
152
+ type = "datetime-local"
153
+ size = "sm"
154
+ onChange = { ( e ) => {
155
+ setEndDate ( e . target . value ) ;
156
+ } }
157
+ />
158
+ </ FormControl >
159
+ </ HStack >
160
+ { isInvalidDateRange && (
161
+ < DismissableAlert
162
+ status = "error"
163
+ title = "Invalid Date Range"
164
+ description = "The start date must be before the end date."
165
+ onClosed = { ( ) => setIsInvalidDateRange ( false ) }
166
+ />
167
+ ) }
168
+ < Box >
169
+ < Button
170
+ size = "sm"
171
+ onClick = { onApplyDateRange }
172
+ aria-disabled = { fetchStatus === "fetching" }
173
+ type = "submit"
174
+ >
175
+ Apply Date Range
176
+ </ Button >
177
+ </ Box >
178
+ </ Stack >
179
+ ) ;
180
+
97
181
return (
98
182
< Stack spacing = { 4 } mb = { 8 } border = "solid 1px" borderColor = "gray.700" borderRadius = "md" >
99
183
< Box >
@@ -111,17 +195,17 @@ export const RequestHistory = () => {
111
195
< Box srOnly aria-live = "polite" >
112
196
{ status === "loading" && (
113
197
< span >
114
- Loading request history rows $ { skip + 1 } through $ { skip + limit }
198
+ Loading request history rows { skip + 1 } through { skip + limit }
115
199
</ span >
116
200
) }
117
201
{ status === "success" && (
118
202
< span >
119
- Finished loading request history rows $ { skip + 1 } through $ { skip + limit }
203
+ Finished loading request history rows { skip + 1 } through { skip + limit }
120
204
</ span >
121
205
) }
122
206
{ status === "success" && fetchStatus === "fetching" && (
123
207
< span >
124
- Loading request history rows $ { skip + 1 } through $ { skip + limit }
208
+ Loading request history rows { skip + 1 } through { skip + limit }
125
209
</ span >
126
210
) }
127
211
</ Box >
@@ -145,13 +229,14 @@ export const RequestHistory = () => {
145
229
</ Alert >
146
230
) }
147
231
{ hasNoData && (
148
- < Text color = "whiteAlpha.700" >
149
- No historical requests found. This is likely because the feed has not been polled yet -
150
- please check back later.
151
- </ Text >
232
+ < Stack >
233
+ { dateRangeForm }
234
+ < Text color = "whiteAlpha.700" > No requests found. </ Text >
235
+ </ Stack >
152
236
) }
153
237
{ data && ! hasNoData && (
154
238
< Stack >
239
+ { dateRangeForm }
155
240
< Box >
156
241
< TableContainer >
157
242
< Table size = "sm" variant = "simple" aria-labelledby = "request-history-table-title" >
0 commit comments