2020-06-16 00:36:59 +02:00
|
|
|
import React, { useState, useEffect, forwardRef } from 'react';
|
2020-10-01 21:17:43 +02:00
|
|
|
import dayjs from 'dayjs';
|
2020-06-13 00:21:58 +02:00
|
|
|
import styled from 'styled-components';
|
2020-04-13 00:45:51 +02:00
|
|
|
import DatePicker from 'react-datepicker';
|
2020-06-13 00:21:58 +02:00
|
|
|
import _ from 'lodash';
|
2020-04-13 00:45:51 +02:00
|
|
|
import 'react-datepicker/dist/react-datepicker.css';
|
2020-06-13 00:21:58 +02:00
|
|
|
import { getYear, getMonth } from 'date-fns';
|
2020-07-17 02:40:23 +02:00
|
|
|
import { useForm, Controller } from 'react-hook-form';
|
2020-08-23 19:27:56 +02:00
|
|
|
import NOOP from 'shared/utils/noop';
|
|
|
|
|
|
|
|
import { Wrapper, ActionWrapper, RemoveDueDate, DueDateInput, DueDatePickerWrapper, ConfirmAddDueDate } from './Styles';
|
2020-04-13 00:45:51 +02:00
|
|
|
|
|
|
|
type DueDateManagerProps = {
|
|
|
|
task: Task;
|
|
|
|
onDueDateChange: (task: Task, newDueDate: Date) => void;
|
2020-06-19 01:12:15 +02:00
|
|
|
onRemoveDueDate: (task: Task) => void;
|
2020-04-13 00:45:51 +02:00
|
|
|
onCancel: () => void;
|
|
|
|
};
|
2020-06-13 00:21:58 +02:00
|
|
|
|
2020-06-16 00:36:59 +02:00
|
|
|
const Form = styled.form`
|
|
|
|
padding-top: 25px;
|
|
|
|
`;
|
|
|
|
|
|
|
|
const FormField = styled.div`
|
|
|
|
width: 50%;
|
|
|
|
display: inline-block;
|
|
|
|
`;
|
2020-06-13 00:21:58 +02:00
|
|
|
const HeaderSelectLabel = styled.div`
|
|
|
|
display: inline-block;
|
|
|
|
position: relative;
|
|
|
|
z-index: 9999;
|
|
|
|
border-radius: 3px;
|
|
|
|
cursor: pointer;
|
|
|
|
padding: 6px 10px;
|
|
|
|
text-decoration: underline;
|
|
|
|
margin: 6px 0;
|
|
|
|
font-size: 14px;
|
|
|
|
line-height: 16px;
|
|
|
|
margin-left: 0;
|
|
|
|
margin-right: 0;
|
|
|
|
padding-left: 4px;
|
|
|
|
padding-right: 4px;
|
|
|
|
color: #c2c6dc;
|
|
|
|
|
|
|
|
&:hover {
|
2020-12-18 00:13:34 +01:00
|
|
|
background: ${props => props.theme.colors.primary};
|
2020-06-13 00:21:58 +02:00
|
|
|
color: #c2c6dc;
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
const HeaderSelect = styled.select`
|
|
|
|
text-decoration: underline;
|
|
|
|
font-size: 14px;
|
|
|
|
text-align: center;
|
|
|
|
padding: 4px 6px;
|
|
|
|
background: none;
|
|
|
|
outline: none;
|
|
|
|
border: none;
|
|
|
|
border-radius: 3px;
|
|
|
|
appearance: none;
|
|
|
|
|
|
|
|
&:hover {
|
2020-12-18 00:13:34 +01:00
|
|
|
background: ${props => props.theme.colors.bg.secondary};
|
|
|
|
border: 1px solid ${props => props.theme.colors.primary};
|
2020-06-13 00:21:58 +02:00
|
|
|
outline: none !important;
|
|
|
|
box-shadow: none;
|
|
|
|
color: #c2c6dc;
|
|
|
|
}
|
|
|
|
|
|
|
|
&::-ms-expand {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
position: absolute;
|
|
|
|
z-index: 9998;
|
|
|
|
margin: 0;
|
|
|
|
left: 0;
|
|
|
|
top: 5px;
|
|
|
|
opacity: 0;
|
|
|
|
`;
|
|
|
|
|
|
|
|
const HeaderButton = styled.button`
|
|
|
|
cursor: pointer;
|
|
|
|
color: #c2c6dc;
|
|
|
|
text-decoration: underline;
|
|
|
|
font-size: 14px;
|
|
|
|
text-align: center;
|
|
|
|
padding: 6px 10px;
|
|
|
|
margin: 6px 0;
|
|
|
|
background: none;
|
|
|
|
outline: none;
|
|
|
|
border: none;
|
|
|
|
border-radius: 3px;
|
|
|
|
&:hover {
|
2020-12-18 00:13:34 +01:00
|
|
|
background: ${props => props.theme.colors.primary};
|
2020-06-13 00:21:58 +02:00
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
const HeaderActions = styled.div`
|
|
|
|
position: relative;
|
|
|
|
text-align: center;
|
|
|
|
& > button:first-child {
|
|
|
|
float: left;
|
|
|
|
}
|
|
|
|
& > button:last-child {
|
|
|
|
float: right;
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
2020-06-19 01:12:15 +02:00
|
|
|
const DueDateManager: React.FC<DueDateManagerProps> = ({ task, onDueDateChange, onRemoveDueDate, onCancel }) => {
|
2020-10-01 21:17:43 +02:00
|
|
|
const now = dayjs();
|
2020-08-29 03:59:45 +02:00
|
|
|
const { register, handleSubmit, errors, setValue, setError, formState, control } = useForm<DueDateFormData>();
|
2020-04-13 00:45:51 +02:00
|
|
|
const [startDate, setStartDate] = useState(new Date());
|
|
|
|
|
2020-06-16 00:36:59 +02:00
|
|
|
useEffect(() => {
|
2020-10-01 21:17:43 +02:00
|
|
|
const newDate = dayjs(startDate).format('YYYY-MM-DD');
|
2020-08-29 03:59:45 +02:00
|
|
|
setValue('endDate', newDate);
|
|
|
|
}, [startDate]);
|
2020-06-16 00:36:59 +02:00
|
|
|
|
2020-06-13 00:21:58 +02:00
|
|
|
const years = _.range(2010, getYear(new Date()) + 10, 1);
|
|
|
|
const months = [
|
|
|
|
'January',
|
|
|
|
'February',
|
|
|
|
'March',
|
|
|
|
'April',
|
|
|
|
'May',
|
|
|
|
'June',
|
|
|
|
'July',
|
|
|
|
'August',
|
|
|
|
'September',
|
|
|
|
'October',
|
|
|
|
'November',
|
|
|
|
'December',
|
|
|
|
];
|
2020-06-16 00:36:59 +02:00
|
|
|
const saveDueDate = (data: any) => {
|
2020-10-01 21:17:43 +02:00
|
|
|
const newDate = dayjs(`${data.endDate} ${dayjs(data.endTime).format('h:mm A')}`, 'YYYY-MM-DD h:mm A');
|
2020-06-16 00:36:59 +02:00
|
|
|
if (newDate.isValid()) {
|
|
|
|
onDueDateChange(task, newDate.toDate());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const CustomTimeInput = forwardRef(({ value, onClick }: any, $ref: any) => {
|
|
|
|
return (
|
|
|
|
<DueDateInput
|
|
|
|
id="endTime"
|
2020-08-29 03:59:45 +02:00
|
|
|
value={value}
|
2020-06-16 00:36:59 +02:00
|
|
|
name="endTime"
|
|
|
|
ref={$ref}
|
|
|
|
width="100%"
|
|
|
|
variant="alternate"
|
2020-08-29 03:59:45 +02:00
|
|
|
label="Time"
|
2020-06-16 00:36:59 +02:00
|
|
|
onClick={onClick}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
});
|
2020-04-13 00:45:51 +02:00
|
|
|
return (
|
|
|
|
<Wrapper>
|
2020-06-16 00:36:59 +02:00
|
|
|
<Form onSubmit={handleSubmit(saveDueDate)}>
|
|
|
|
<FormField>
|
|
|
|
<DueDateInput
|
|
|
|
id="endDate"
|
|
|
|
name="endDate"
|
|
|
|
width="100%"
|
|
|
|
variant="alternate"
|
|
|
|
label="Date"
|
2020-08-29 03:59:45 +02:00
|
|
|
defaultValue={now.format('YYYY-MM-DD')}
|
2020-06-16 00:36:59 +02:00
|
|
|
ref={register({
|
|
|
|
required: 'End date is required.',
|
|
|
|
})}
|
|
|
|
/>
|
|
|
|
</FormField>
|
|
|
|
<FormField>
|
2020-07-17 02:40:23 +02:00
|
|
|
<Controller
|
|
|
|
control={control}
|
2020-08-29 03:59:45 +02:00
|
|
|
defaultValue={now.toDate()}
|
2020-07-17 02:40:23 +02:00
|
|
|
name="endTime"
|
|
|
|
render={({ onChange, onBlur, value }) => (
|
|
|
|
<DatePicker
|
|
|
|
onChange={onChange}
|
|
|
|
selected={value}
|
|
|
|
onBlur={onBlur}
|
|
|
|
showTimeSelect
|
|
|
|
showTimeSelectOnly
|
|
|
|
timeIntervals={15}
|
|
|
|
timeCaption="Time"
|
|
|
|
dateFormat="h:mm aa"
|
|
|
|
customInput={<CustomTimeInput />}
|
|
|
|
/>
|
|
|
|
)}
|
2020-06-16 00:36:59 +02:00
|
|
|
/>
|
|
|
|
</FormField>
|
|
|
|
<DueDatePickerWrapper>
|
|
|
|
<DatePicker
|
|
|
|
useWeekdaysShort
|
|
|
|
renderCustomHeader={({
|
|
|
|
date,
|
|
|
|
changeYear,
|
|
|
|
changeMonth,
|
|
|
|
decreaseMonth,
|
|
|
|
increaseMonth,
|
|
|
|
prevMonthButtonDisabled,
|
|
|
|
nextMonthButtonDisabled,
|
|
|
|
}) => (
|
|
|
|
<HeaderActions>
|
|
|
|
<HeaderButton onClick={decreaseMonth} disabled={prevMonthButtonDisabled}>
|
|
|
|
Prev
|
|
|
|
</HeaderButton>
|
|
|
|
<HeaderSelectLabel>
|
|
|
|
{months[date.getMonth()]}
|
2020-08-23 19:27:56 +02:00
|
|
|
<HeaderSelect
|
|
|
|
value={getYear(date)}
|
|
|
|
onChange={({ target: { value } }) => changeYear(parseInt(value, 10))}
|
|
|
|
>
|
2020-06-16 00:36:59 +02:00
|
|
|
{years.map(option => (
|
|
|
|
<option key={option} value={option}>
|
|
|
|
{option}
|
|
|
|
</option>
|
|
|
|
))}
|
|
|
|
</HeaderSelect>
|
|
|
|
</HeaderSelectLabel>
|
|
|
|
<HeaderSelectLabel>
|
|
|
|
{date.getFullYear()}
|
|
|
|
<HeaderSelect
|
|
|
|
value={months[getMonth(date)]}
|
|
|
|
onChange={({ target: { value } }) => changeMonth(months.indexOf(value))}
|
|
|
|
>
|
|
|
|
{months.map(option => (
|
|
|
|
<option key={option} value={option}>
|
|
|
|
{option}
|
|
|
|
</option>
|
|
|
|
))}
|
|
|
|
</HeaderSelect>
|
|
|
|
</HeaderSelectLabel>
|
|
|
|
|
|
|
|
<HeaderButton onClick={increaseMonth} disabled={nextMonthButtonDisabled}>
|
|
|
|
Next
|
|
|
|
</HeaderButton>
|
|
|
|
</HeaderActions>
|
|
|
|
)}
|
|
|
|
selected={startDate}
|
|
|
|
inline
|
|
|
|
onChange={date => {
|
2020-08-29 03:59:45 +02:00
|
|
|
if (date) {
|
|
|
|
setStartDate(date);
|
|
|
|
}
|
2020-06-16 00:36:59 +02:00
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</DueDatePickerWrapper>
|
|
|
|
<ActionWrapper>
|
2020-08-23 19:27:56 +02:00
|
|
|
<ConfirmAddDueDate type="submit" onClick={NOOP}>
|
2020-06-19 01:12:15 +02:00
|
|
|
Save
|
|
|
|
</ConfirmAddDueDate>
|
|
|
|
<RemoveDueDate
|
|
|
|
variant="outline"
|
|
|
|
color="danger"
|
2020-06-16 00:36:59 +02:00
|
|
|
onClick={() => {
|
2020-06-19 01:12:15 +02:00
|
|
|
onRemoveDueDate(task);
|
2020-06-16 00:36:59 +02:00
|
|
|
}}
|
|
|
|
>
|
2020-06-19 01:12:15 +02:00
|
|
|
Remove
|
|
|
|
</RemoveDueDate>
|
2020-06-16 00:36:59 +02:00
|
|
|
</ActionWrapper>
|
|
|
|
</Form>
|
2020-04-13 00:45:51 +02:00
|
|
|
</Wrapper>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default DueDateManager;
|