SelectWindow.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. import React, { useEffect, useState } from 'react'
  2. import { makeStyles } from '@material-ui/styles'
  3. import { endOfDay, startOfDay } from 'date-fns'
  4. import { MuiPickersUtilsProvider, KeyboardDatePicker } from '@material-ui/pickers'
  5. import Button from '@material-ui/core/Button'
  6. import DateFnsUtils from '@date-io/date-fns'
  7. import FormControl from '@material-ui/core/FormControl'
  8. import Link from '@material-ui/core/Link'
  9. import Popover from '@material-ui/core/Popover'
  10. import TextField from '@material-ui/core/TextField'
  11. import Typography from '@material-ui/core/Typography'
  12. import { isValid } from 'date-fns'
  13. import { find, get } from 'lodash'
  14. const useStyles = makeStyles({
  15. dateContainer: {
  16. paddingLeft: 18,
  17. paddingRight: 18,
  18. paddingTop: 6,
  19. paddingBottom: 18,
  20. display: 'flex',
  21. flexFlow: 'row',
  22. },
  23. dateContainerColumn: {
  24. display: 'flex',
  25. flexFlow: 'column',
  26. },
  27. formControl: {
  28. margin: 8,
  29. width: 120,
  30. },
  31. })
  32. const SelectWindow = ({ windowOptions, window, setWindow }) => {
  33. const classes = useStyles()
  34. const [anchorEl, setAnchorEl] = useState(null)
  35. const [startDate, setStartDate] = useState(null)
  36. const [endDate, setEndDate] = useState(null)
  37. const [intervalString, setIntervalString] = useState(null)
  38. const handleClick = (event) => {
  39. setAnchorEl(event.currentTarget)
  40. }
  41. const handleClose = () => {
  42. setAnchorEl(null)
  43. }
  44. const handleStartDateChange = (date) => {
  45. if (isValid(date)) {
  46. setStartDate(startOfDay(date))
  47. }
  48. }
  49. const handleEndDateChange = (date) => {
  50. if (isValid(date)) {
  51. setEndDate(endOfDay(date))
  52. }
  53. }
  54. const handleSubmitPresetDates = (dateString) => {
  55. setWindow(dateString)
  56. setStartDate(null)
  57. setEndDate(null)
  58. handleClose()
  59. }
  60. const handleSubmitCustomDates = () => {
  61. if (intervalString !== null) {
  62. setWindow(intervalString)
  63. handleClose()
  64. }
  65. }
  66. useEffect(() => {
  67. if (startDate !== null && endDate !== null) {
  68. // Note: getTimezoneOffset() is calculated based on current system locale, NOT date object
  69. let adjustedStartDate = new Date(startDate - startDate.getTimezoneOffset() * 60000)
  70. let adjustedEndDate = new Date(endDate - endDate.getTimezoneOffset() * 60000)
  71. setIntervalString(
  72. adjustedStartDate.toISOString().split('.')[0] + "Z"
  73. + ","
  74. + adjustedEndDate.toISOString().split('.')[0] + "Z"
  75. )
  76. }
  77. }, [startDate, endDate])
  78. const open = Boolean(anchorEl)
  79. const id = open ? 'date-range-popover' : undefined
  80. return (
  81. <>
  82. <FormControl className={classes.formControl}>
  83. <TextField
  84. id="filled-read-only-input"
  85. label="Date Range"
  86. value={get(find(windowOptions, { value: window }), "name", "Custom")}
  87. onClick={e => handleClick(e)}
  88. inputProps={{
  89. readOnly: true,
  90. style: { cursor: 'pointer' },
  91. }}
  92. />
  93. </FormControl>
  94. <Popover
  95. id={id}
  96. open={open}
  97. anchorEl={anchorEl}
  98. onClose={handleClose}
  99. anchorOrigin={{
  100. vertical: 'bottom',
  101. horizontal: 'left',
  102. }}
  103. transformOrigin={{
  104. vertical: 'top',
  105. horizontal: 'center',
  106. }}
  107. >
  108. <div className={classes.dateContainer}>
  109. <div className={classes.dateContainerColumn}>
  110. <MuiPickersUtilsProvider utils={DateFnsUtils}>
  111. <KeyboardDatePicker
  112. style={{ width: '144px' }}
  113. autoOk={true}
  114. disableToolbar
  115. variant="inline"
  116. format="MM/dd/yyyy"
  117. margin="normal"
  118. id="date-picker-start"
  119. label="Start Date"
  120. value={startDate}
  121. maxDate={new Date()}
  122. maxDateMessage="Date should not be after today."
  123. onChange={handleStartDateChange}
  124. KeyboardButtonProps={{
  125. 'aria-label': 'change date',
  126. }}
  127. />
  128. <KeyboardDatePicker
  129. style={{ width: '144px' }}
  130. autoOk={true}
  131. disableToolbar
  132. variant="inline"
  133. format="MM/dd/yyyy"
  134. margin="normal"
  135. id="date-picker-end"
  136. label="End Date"
  137. value={endDate}
  138. maxDate={new Date()}
  139. maxDateMessage="Date should not be after today."
  140. onChange={handleEndDateChange}
  141. KeyboardButtonProps={{
  142. 'aria-label': 'change date',
  143. }}
  144. />
  145. </MuiPickersUtilsProvider>
  146. <div>
  147. <Button
  148. style={{ marginTop: 16 }}
  149. variant="contained"
  150. color="default"
  151. onClick={handleSubmitCustomDates}
  152. >
  153. Apply
  154. </Button>
  155. </div>
  156. </div>
  157. <div className={classes.dateContainerColumn} style={{ paddingTop: 12, marginLeft: 18 }}>
  158. {windowOptions.map(opt =>
  159. <Typography key={opt.value}
  160. >
  161. <Link
  162. style={{ cursor: "pointer" }}
  163. key={opt.value}
  164. value={opt.value}
  165. onClick={() => handleSubmitPresetDates(opt.value)}
  166. >
  167. {opt.name}
  168. </Link>
  169. </Typography>
  170. )}
  171. </div>
  172. </div>
  173. </Popover>
  174. </>
  175. )
  176. }
  177. export default React.memo(SelectWindow)