Skip to content

Commit 3789e79

Browse files
committed
Allow for setting phase dates by duration *or* end date
1 parent b79cfc4 commit 3789e79

File tree

3 files changed

+106
-9
lines changed

3 files changed

+106
-9
lines changed

src/components/DateInput/index.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React, { useEffect, useState, useImperativeHandle, forwardRef } from 'react'
2+
import PropTypes from 'prop-types'
3+
import 'react-day-picker/lib/style.css'
4+
import 'rc-time-picker/assets/index.css'
5+
import DateTime from '@nateradebaugh/react-datetime'
6+
import '@nateradebaugh/react-datetime/scss/styles.scss'
7+
8+
const DateInput = forwardRef(({
9+
onChange,
10+
value,
11+
isValidDate,
12+
dateFormat,
13+
timeFormat,
14+
className
15+
}, ref) => {
16+
const [localValue, setLocalValue] = useState(value)
17+
useEffect(() => {
18+
setLocalValue(value)
19+
}, [value])
20+
21+
useImperativeHandle(ref, () => ({
22+
forceReset: () => {
23+
setLocalValue(value)
24+
}
25+
}))
26+
27+
return (
28+
<DateTime
29+
className={className}
30+
value={localValue}
31+
onChange={newValue => {
32+
setLocalValue(newValue)
33+
}}
34+
onBlur={onChange}
35+
isValidDate={isValidDate}
36+
dateFormat={dateFormat}
37+
timeFormat={timeFormat}
38+
/>
39+
)
40+
})
41+
42+
DateInput.defaultProps = {
43+
onChange: () => {},
44+
isValidDate: () => true,
45+
value: null,
46+
dateFormat: null,
47+
timeFormat: null,
48+
className: null
49+
}
50+
51+
DateInput.propTypes = {
52+
onChange: PropTypes.func,
53+
isValidDate: PropTypes.func,
54+
value: PropTypes.any,
55+
dateFormat: PropTypes.string,
56+
timeFormat: PropTypes.string,
57+
className: PropTypes.string
58+
}
59+
export default DateInput

src/components/PhaseInput/index.js

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
import moment from 'moment'
2-
import React, { useEffect, useMemo } from 'react'
2+
import React, { useEffect, useMemo, useRef } from 'react'
33
import PropTypes from 'prop-types'
44
import styles from './PhaseInput.module.scss'
55
import cn from 'classnames'
6-
import 'react-day-picker/lib/style.css'
7-
import 'rc-time-picker/assets/index.css'
8-
import DateTime from '@nateradebaugh/react-datetime'
96
import isAfter from 'date-fns/isAfter'
107
import subDays from 'date-fns/subDays'
11-
import '@nateradebaugh/react-datetime/scss/styles.scss'
128
import DurationInput from '../DurationInput'
13-
import { getPhaseHoursMinutes, getPhaseEndDate } from '../../util/date'
9+
import { getPhaseHoursMinutes, getPhaseEndDate, getPhaseDuration } from '../../util/date'
10+
import DateInput from '../DateInput'
1411

1512
const dateFormat = 'MM/DD/YYYY HH:mm'
1613
const inputDateFormat = 'MM/dd/yyyy'
@@ -21,6 +18,7 @@ const PhaseInput = ({ onUpdatePhase, phase, readOnly, phaseIndex }) => {
2118
const { scheduledStartDate: startDate, scheduledEndDate: endDate, duration, isStartTimeActive, isDurationActive } = phase
2219

2320
const durationHoursMinutes = useMemo(() => getPhaseHoursMinutes(duration), [duration])
21+
const endDateInputRef = useRef()
2422

2523
const onStartDateChange = (e) => {
2624
let startDate = moment(e).format(dateFormat)
@@ -32,6 +30,20 @@ const PhaseInput = ({ onUpdatePhase, phase, readOnly, phaseIndex }) => {
3230
})
3331
}
3432

33+
const onEndDateChange = (e) => {
34+
let endDate = moment(e).format(dateFormat)
35+
let duration = getPhaseDuration(startDate, endDate)
36+
if (duration > 0) {
37+
onUpdatePhase({
38+
startDate,
39+
endDate,
40+
duration
41+
})
42+
} else {
43+
endDateInputRef.current.forceReset()
44+
}
45+
}
46+
3547
useEffect(() => {
3648
if (!startDate && onUpdatePhase) {
3749
let startDate = moment().format(dateFormat)
@@ -71,9 +83,9 @@ const PhaseInput = ({ onUpdatePhase, phase, readOnly, phaseIndex }) => {
7183
<span className={styles.readOnlyValue}>{moment(startDate).format(dateFormat)}</span>
7284
)
7385
: (
74-
<DateTime
86+
<DateInput
7587
className={styles.dateTimeInput}
76-
value={moment(startDate).format(dateFormat)}
88+
value={moment(startDate).toDate()}
7789
onChange={onStartDateChange}
7890
isValidDate={(current) => {
7991
const yesterday = subDays(new Date(), 1)
@@ -87,7 +99,21 @@ const PhaseInput = ({ onUpdatePhase, phase, readOnly, phaseIndex }) => {
8799
<div className={cn(styles.field, styles.col2)}>
88100
<span className={styles.title}>End Date:</span>
89101
<div className={styles.dayPicker}>
90-
<span className={styles.readOnlyValue}>{moment(endDate).format(dateFormat)}</span>
102+
{(readOnly || !isDurationActive) ? (
103+
<span className={styles.readOnlyValue}>{moment(endDate).format(dateFormat)}</span>
104+
) : (
105+
<DateInput
106+
ref={endDateInputRef}
107+
className={styles.dateTimeInput}
108+
value={moment(endDate).toDate()}
109+
onChange={onEndDateChange}
110+
isValidDate={(current) => {
111+
return isAfter(current, moment(startDate).toDate())
112+
}}
113+
dateFormat={inputDateFormat}
114+
timeFormat={inputTimeFormat}
115+
/>
116+
)}
91117
</div>
92118
</div>
93119
<div className={cn(styles.field, styles.col2)}>

src/util/date.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,18 @@ export const getPhaseEndDate = (startDate, duration) => {
5757
return moment(startDate).add(duration, 'minutes').format(dateFormat)
5858
}
5959

60+
/**
61+
* Get phase duration
62+
* @param {Date} startDate phase start date
63+
* @param {Date} endDate phase end date
64+
* @returns duration
65+
*/
66+
export const getPhaseDuration = (startDate, endDate) => {
67+
const startDateMoment = moment(startDate).set({ second: 0, millisecond: 0 })
68+
const endDateMoment = moment(endDate).set({ second: 0, millisecond: 0 })
69+
return moment.duration(endDateMoment.diff(startDateMoment)).asMinutes()
70+
}
71+
6072
/**
6173
* Get phase end date in date
6274
* @param {Date} startDate phase start date

0 commit comments

Comments
 (0)